为什么在乘以和除以整个整数时会失去精度?

Col*_*vis 7 python python-3.x

我曾经认为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
Run Code Online (Sandbox Code Playgroud)

如果我使用地板分割,这似乎有效 - 但是 -

>>> c = b//2
>>> c
313585730727764141482831584863
>>> a == c
True
Run Code Online (Sandbox Code Playgroud)

Python 2.7似乎也避免了这个场景,保留它们 longs

>>> a = 313585730727764141482831584863
>>> a
313585730727764141482831584863L
>>> b = a*2
>>> c = b /2
>>> a
313585730727764141482831584863L
>>> c
313585730727764141482831584863L
>>> a == c
True
Run Code Online (Sandbox Code Playgroud)

我很感激任何见解!谢谢!

Mar*_*ers 11

您正在使用真正的除法运算符进行除法/,这将始终生成浮点值.改为使用floor division //来获得整数结果:

>>> a = 313585730727764141482831584863
>>> b = a*2
>>> c = b // 2
>>> a == c
True
Run Code Online (Sandbox Code Playgroud)

您的计算机硬件无法以所需的精度处理浮点值.

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

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

from __future__ import division
Run Code Online (Sandbox Code Playgroud)

行为发生了变化,因为仅使用整数运算符和使用至少一个float参数之间的区别令人困惑.

换言之,标准Python 2 /操作者是不同的从Python 3兽/除法运算符.当应用于两个整数操作数,它的行为就像//在Python 3.地板除法运算符但如果两个操作数中的任一个是一个浮子代替,那么它的作用类似于/浮子除法运算符,而不是.上面的__future__导入为Python 3 /中的真正除法运算符交换了Python 2 运算符.

你可以在反汇编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        
Run Code Online (Sandbox Code Playgroud)

__future__进口造成了Python的编译器使用不同的字节码除法运算,交换BINARY_DIVIDE进行BINARY_TRUE_DIVIDE.

  • 不,在Python 3中使用`/`总是**导致浮点结果.这是关于一致性,而不是事先知道操作数.Python 2的行为是一个导致混淆的错误.引入了一个新的运营商来缓解这个问题. (2认同)