我在python Shell中输入了以下代码:
>>>1/10**323
1e-323
>>>1/10**324
0.0
可以看到,结果是出乎意料的。有人知道为什么会发生这种情况或者如何改变这种情况吗?此外,我还得到了这个错误:
>>> 1/10**323.1
Traceback (most recent call last):
File "<pyshell#21>", line 1, in <module>
1/10**323.1
OverflowError: (34, 'Result too large')
如有任何意见,不胜感激。
这些问题直接来自浮点数,更准确地说来自IEEE 754,这是大多数常用硬件和大多数软件使用的标准。
Pythonfloat
是双精度IEEE 754浮点数类型,这意味着它使用恰好8字节(64位)存储float
类型的所有数字。1位用于存储数字的正负,11位用于指数(科学记数法中e
之后的部分),53位用于有效位数(e
之前的部分)。
1/10**324
的实际值如此接近于零,以至于64位浮点数无法表示它。在进行浮点计算时几乎总是会有一些错误,这是不可避免的,但是当你如此接近零时,它就会更加明显!
这个错误不是因为除法。10**323.1
甚至10**323.0
也会出现同样的错误。
Python整数是可变大小的,你可以制作越来越大的数字,占用越来越多的字节来存储。这意味着整数操作(如10**324
)不会溢出。但是如果使用int ** float
,结果可能不是整数,因此必须将其存储在浮点数中。大数的幂运算很容易得到一个64位无法容纳的数。你是怎么做的?嗯,有两个选项:
- 使用最大可能的值,在标准中标记为
Infinity
。这就是JavaScript的功能。 - 要谨慎,防止程序员犯错误。什么错误?好吧,
10 ** 500 / 10 ** 499
应该是10
,但如果10 ** 500
的计算结果是Infinity
,10 ** 499
也是,你最终会得到Infinity / Infinity
,这是不确定的,要么出错,要么给出一个特殊的答案(称为NaN
,因为"不是数字"),但你不会得到你的10
。
在Python 2中,int / int
曾经是现在的int // int
,这意味着5 / 2
曾经是2
。在Python 3中,这个问题得到了纠正。除法的结果在实践中经常不是整数,因此像float / float
那样对待它更有意义。作为副作用,4 / 2
现在是2.0
而不是2
。