Mar-19-2018, 01:51 AM
(Mar-18-2018, 11:25 PM)quazirfan Wrote:(Mar-17-2018, 11:40 PM)casevh Wrote: In Python 2, math.floor(a/b) is equivalent to FLOOR(float(floordiv(a,b))).
Why would it cast it to float? The precision is lost already when floordiv is used.
The following paragraph is true for Python 1 and 2.
The math module was originally written to provide access to the C math library. All arguments to functions in the C math must be converted to a supported floating point type. For Python, this is almost always a C double. The result of floordiv(int, int) remains an int so it must do the cast to float (technically a C double behind the scenes). The conversion from Python's arbitrary precision integers to C double is only reliable for values less than 2**53.
Here is an example for Python 2. Note that
/
and //
and return the same result.>>> 10**200/10**100 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L >>> 10**200//10**100 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000L >>> math.floor(10**200/10**100) 1e+100 >>> int(math.floor(10**200/10**100)) 10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104LPython 3 is different since truediv is used and that already returns a float (aka C double). Then the C math library's floor function is called. And finally, the result is converted to an integer. But in Python 3, math.floor behaves differently if the argument is an integer.
Here is a Python 3 example.
>>> 10**200/10**100 1e+100 >>> math.floor(10**200/10**100) 10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104 >>> 10**200//10**100 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 >>> math.floor(10**200//10**100) 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 >>>Note the different results. In Python 3, the return types of math.floor, math.ceil, and math.trunc were changed to be an integer. The argument handling logic was also changed. If the argument is a type other than the native Python float, the functions will attempt to call the type's corresponding special methods: __floor__, __ceil__, or __trunc__.
If you are working with integer arguments, why would you want to use math.floor?
//
is faster for small values, always accurate and consistent, and behaves identically between Python 2 and Python 3.$ py27 -m timeit -s "import math;a=10;b=3;f=math.floor" "f(a/b)" 10000000 loops, best of 3: 0.0444 usec per loop $ py27 -m timeit -s "a=10;b=3" "a//b" 10000000 loops, best of 3: 0.0277 usec per loop $ py27 -m timeit -s "from math import floor;a=10**200;b=10**100" "floor(a/b)" 1000000 loops, best of 3: 0.431 usec per loop $ py27 -m timeit -s "a=10**200;b=10**100" "a//b" 1000000 loops, best of 3: 0.389 usec per loopNote: the third example is faster with Python 3 and large numbers but then it is producing incorrect results.
casevh