Question

I'm currently having some issues with the math.floor() function in python. I am attempting to compute the following value:

math.floor((3710402416420168191+3710402416420167681)/2)

This is producing the answer

3710402416420167680

Which I know is not right. I think this has something to do with Python's ability to do arithmetic with very large numbers -- can anyone help out?

Thanks!

Was it helpful?

Solution

Avoid using floating point numbers. Python only uses 53 bits of precision for floating point numbers, but integers can grow arbitrarily large:

>>> int((3710402416420168191 + 3710402416420167681) / 2)
3710402416420167680
>>> (3710402416420168191 + 3710402416420167681) // 2
3710402416420167936

// is floor division, so it'll return the integral part of the result without resorting to floats (which is what math.floor returns).

OTHER TIPS

I can't reproduce your results, in my machine this:

math.floor((3710402416420168191+3710402416420167681)/2)

Is returning this, which is correct for the given precision:

3.7104024164201677e+18

Maybe the error happens when you try to print the above result? which clearly has lost some precision, because math.floor() returns a float, not an integer.

Python can perform integer arithmetic with arbitrary precision, but is limited in the number of significant digits with which to represent the floating point average. If the two numbers are close enough together, you may have better luck with

x = 3710402416420168191
y = 3710402416420167681
math.floor( x - (x-y)/2.0 )

Far fewer significant digits are necessary to hold the difference of x and y than their sum.

UPDATE: on closer inspection, the problem is not with the math, but with converting the resulting large integer to a float, which cannot represent the integer precisely. The integer result

(3710402416420168191+3710402416420167681)/2

is correct, but passing that value to math.floor results in the poorly rounded value.

The mean of those two numbers is larger than the number of decimal digits that can be faithfully represented by a float:

 import sys
 print sys.float_info

Output:

 sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

dig=15 means that only 15 significant digits can be reliably represented in a float. See the docs here for more info.

As others have pointed out, there is no such problem if you use integers and floor division:

(3710402416420168191+3710402416420167681)//2

Output:

3710402416420167936
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top