8

Python3 は任意の長さの数値を処理できるはずだと思っていましたが、一貫して動作しないように見えるという問題に直面しています。

乗算してから除算した後、私の int は内部表現を変更したようで、以前の自己との一致として評価されなくなりました。

小数や分数を使用せずに整数を使用していますが、丸めによって精度が失われているように動作しています..?

なぜこれが起こっているのかについての洞察をいただければ幸いです。コードには回避策がありますが、結果が直感に反するため、動作の背後にあるものを知りたいです;)

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

これは、フロア分割を使用するとうまくいくようですが、しかし-

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

Python 2.7 もこのシーンを避けているようで、longs

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

洞察をいただければ幸いです。ありがとうございました!

4

1 に答える 1

13

You are dividing using the true division operator /, which will always result in floating point values. Use floor division instead, //, to get integer results:

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

Your computer hardware cannot handle float values with the required precision.

The alternative is to use decimal.Decimal() values, but this will result in slower arithmetic operations.

In Python 2, the / operator is the floor division operator, but when applied to integers only. To get the same behaviour in Python 2, add:

from __future__ import division

The behaviour was changed because the difference between using only integer operators and using at least one float argument was confusing.

In other words, the standard Python 2 / operator is a different beast from the Python 3 / division operator. When applied to two integer operands, it acts just like the // floor division operator in Python 3. But if either one of the two operands is a float instead, then it acts like the / float division operator instead. The above __future__ import swaps out the Python 2 / operator for the true division operator found in Python 3.

You can see this when disassembling 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        

the __future__ import caused the Python compiler to use a different bytecode for the division operator, swapping BINARY_DIVIDE for BINARY_TRUE_DIVIDE.

于 2013-09-14T13:11:08.880 に答える