我想找出这里的模式:
>>> 1e300 ** 2
OverflowError: (34, 'Result too large')
>>> 1e300j ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1j) ** 2
OverflowError: complex exponentiation
>>> (1e300 + 1e300j) ** 2
(nan+nanj)这种行为似乎不仅在理论上没有具体说明,而且在实践中也很奇怪!这是怎么解释的?
发布于 2013-08-14 23:10:38
查看用于复杂指数的来源,就会发现Python只在计算结束时检查溢出。另外,对于小整数指数也有一个特例,它通过平方进行幂运算,这涉及到复数乘法。
r.real = a.real*b.real - a.imag*b.imag;
r.imag = a.real*b.imag + a.imag*b.real;这是复乘法的公式。请注意以下事项:
a.real*b.real - a.imag*b.imag当a和b非常大时,它变成浮点无穷大减去浮点无穷大,即nan。nan结果传播,经过几次操作后,结果是(nan+nanj)。Py_ADJUST_ERANGE2只在看到无穷大时才设置errno,因此它错过了溢出并继续前进。
总之,Python只检查溢出的最终结果,而不是中间值,这会导致它错过中间的溢出,因为它在结束时是所有的nan。确实引起OverflowError的表达式是这样做的,因为它们从不试图减去无穷大,因此在结尾处会发现错误。它看起来不像是一个深思熟虑的设计决策;您可以通过改变溢出检查的工作方式来修复它。
发布于 2013-08-14 22:51:51
好吧,我很确定我已经搞清楚了。
首先,我注意到一件似乎有点可笑的事:
>>> (1e309j)**2
(nan+nanj)
>>> (1e308j)**2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: complex exponentiation有意思的。也许这和复杂的指数根本没有关系。
>>> (1e309)**2
inf
>>> (1e308)**2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')更有趣的是。让我们看看Python对1e309和1e308的看法
>>> (1e308)
1e+308
>>> (1e309)
inf最后,
>>> (1e309)**2
inf
>>> (1e309j)**2
(nan+nanj)和
>>> (float('inf') + 1j) ** 2
(nan+nanj)
>>> (1e309j)
infj
>>> (1e309j)**2
(nan+nanj)对inf的任何操纵都给了我们inf。看起来复数(a + bi)的实现不太倾向于给出inf,而更倾向于给出(nan + nanj)。所以,通常返回inf的东西会返回(nan + nanj) --我不知道为什么会这样,也许对Python的inf和nan有更好理解的人可以跳进去。
简而言之,数字最终不再泛滥,并开始返回inf。用inf计算很容易,但是用接近它的数字进行计算就不容易了!这就是为什么1e309**2工作,而1e308 ** 2不工作。当与复数配对时,这(无论出于什么原因)给出了(nan + nanj)。我只是通过玩游戏机才发现这一点的--我很想看一个更彻底的解释!
编辑:@user2357112给出了一个更好的理由。计算复指数的方法可以包括inf - inf的计算,它返回nan。我将把这个留待显示模式,但他的回答给出了理由。
顺便说一句,我觉得这很有趣:
>>> (float('inf') + 1j) ** 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: complex exponentiation
>>> (float('inf') + 1j)
(inf+1j)发布于 2013-08-14 22:42:36
Python整数值可以自动提升到长时间的任意精度:
>>> (10**300)**2
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000由于IEEE浮点的限制,浮点数溢出
>>> float(10**300)**2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')Python复杂的组件是一个浮点类,但也会发生相同的溢出:
>>> isinstance(complex(1).real,float)
True
>>> isinstance(complex(1).imag,float)
True取通常的最大双精度值:
>>> max_double=1.7976931348623157e+308在浮点范围内执行大多数增加该值的步骤,然后得到inf。
>>> max_double*10
inf
>>> max_double*max_double
inf
>>> max_double*max_double*max_double*max_double
inf
>>> max_double++10**(308-15)
inf如果在FP窗口外,mantisa和指数不变:
>>> md+10**(308-17)
1.7976931348623157e+308
>>> max_double**1.0000000000000001
1.7976931348623157e+308可以看到溢出:
>>> max_double**1.000000000000001
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')但作为在文件中说明,它的应用并不一致:
由于C语言中浮点异常处理缺乏标准化,大多数浮点操作也没有被检查。
在这里可以看到:
>>> (1e300+1e300j)*(1e300+1e300j)
(nan+infj)
>>> (1e300+1e300j)**2
(nan+nanj)https://stackoverflow.com/questions/18243270
复制相似问题