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

您正在使用真正的除法运算符进行除法/,这将始终产生浮点值。改为使用地板除法//, 以获得整数结果:

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

您的计算机硬件无法处理具有所需精度的浮点值。

另一种方法是使用decimal.Decimal()values,但这会导致算术运算速度变慢。

在 Python 2 中,/运算符除法运算符,但应用于整数时。要在 Python 2 中获得相同的行为,请添加:

from __future__ import division

行为已更改,因为仅使用整数运算符和使用至少一个浮点参数之间的区别令人困惑。

换句话说,标准的 Python 2运算符与 Python 3 的除法运算/符是不同的野兽。/当应用于两个整数操作数时,它就像 Python 3 中的地板除法运算符一样。但是如果两个操作数//的任何一个是浮点数,那么它的作用就像/浮点除法运算符一样。上述导入将 Python 2运算符替换为 Python 3 中的真正除法运算符。__future__/

在反汇编 Python 字节码时可以看到:

>>> 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        

__future__导入导致 Python 编译器为除法运算符使用不同的字节码,BINARY_DIVIDE换成BINARY_TRUE_DIVIDE.

于 2013-09-14T13:11:08.880 回答