Why do I lose accuracy when multiplying and dividing integer ints?

I thought Python3 should be able to handle numbers of arbitrary length, but I run into a problem in which they don't seem to act sequentially.

After multiplication, then division, my int seems to have changed its internal representation and no longer evaluates as a coincidence with its former self.

I use integers without any decimals or fractions, but it acts almost as if it were losing rounding accuracy ..?

I would be grateful for why this is happening, and if there is something that I have to do differently. I have workarounds for my code, but since the result is contrary to intuition, I would like to know what kind of behavior;)

Python 3.3.2 (default, Jul 30 2013, 00:52:04) [GCC 4.2.1 Compatible Apple LLVM 4.2 (clang-425.0.28)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> a = 313585730727764141482831584863 >>> a 313585730727764141482831584863 >>> b = a*2 >>> c = b /2 >>> a 313585730727764141482831584863 >>> c 3.1358573072776415e+29 >>> a == c False 

This seems to work if I use gender separation, however -

 >>> c = b//2 >>> c 313585730727764141482831584863 >>> a == c True 

Python 2.7 also avoids this scenerio by storing them in longs

 >>> a = 313585730727764141482831584863 >>> a 313585730727764141482831584863L >>> b = a*2 >>> c = b /2 >>> a 313585730727764141482831584863L >>> c 313585730727764141482831584863L >>> a == c True 

I would be grateful for your insight! Thanks!

+7
python
source share
1 answer

You divide by using the true / operator, which will always have floating point values. Instead, use // to divide the sex to get integer results:

 >>> a = 313585730727764141482831584863 >>> b = a*2 >>> c = b // 2 >>> a == c True 

Computer hardware cannot process floating point values โ€‹โ€‹with the required accuracy.

An alternative is to use decimal.Decimal() values , but this will lead to slower arithmetic operations.

In Python 2, the / operator is a gender division operator, but applies only to integers. To get the same behavior in Python 2, add:

 from __future__ import division 

The behavior was changed because the difference between using only integer operators and using at least one floating-point argument was confusing.

In other words, the standard Python 2 / operator is another beast from the Python 3 / split operator. When applied to two integer operands, it acts the same as the // floor split operator // in Python 3. But if one of the two operands is a float, then it acts like the / float division operator. The above __future__ import collapses the Python 2 / operator for the actual division operator found in Python 3.

This can be seen when parsing Python bytecode:

 >>> import dis >>> def olddivision(x, y): return x / y ... >>> dis.dis(olddivision) 1 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_DIVIDE 7 RETURN_VALUE >>> from __future__ import division >>> def newdivision(x, y): return x / y ... >>> dis.dis(newdivision) 1 0 LOAD_FAST 0 (x) 3 LOAD_FAST 1 (y) 6 BINARY_TRUE_DIVIDE 7 RETURN_VALUE 

importing __future__ forced the Python compiler to use a different bytecode for the division operator, replacing BINARY_DIVIDE with BINARY_TRUE_DIVIDE .

+11
source share

All Articles