1 ** math.nan 和 0j ** math.nan 的意外结果

12

我很吃惊

>>> import math
>>> 1**math.nan
1.0

在我们做这件事的同时,也要考虑到那件事

>>> 0j**math.nan
0j

我没有找到其他的例子。这是否是正确选择的原因或逻辑上的遗漏?还是这是一个错误?

我期望结果是nan,就像除了10j之外的每个数字一样。

编辑1:感谢jedwards在下面的评论中提供的参考资料。但我仍然不明白为什么要这样做。为什么将其确定为标准?此外,找不到关于0j**mat.nan的参考资料...

编辑2:所以根据下面的答案和其他一些内容,逻辑可能是这样的:任何涉及nan的计算都应返回nan,除非计算始终返回相同的答案而不考虑参数。在这种情况下,我们拥有nan作为参数的事实不应影响结果,我们仍应该得到固定的答案。

这肯定解释了1**math.nanmath.nan**0。这也解释了为什么0**math.nan给出nan而不是0(因为0**n对于所有n除了当n = 0时结果为1),并且可以扩展到涵盖为什么如果我们认为参数不必是有限的,那么math.nan*0nan

但是,如果这是幕后逻辑,那么0j**math.nan应该是nan,因为0j**n对于所有的n都是0,除了n=0,在这种情况下0j**01。那么... 0j**math.nan是否有不同的推理?还是实现上出了问题?


3
nan**0 等于 1,这是你清单上的另一个惊喜。 - wim
2
我之前错误地认为它是IEEE-754,但实际上它看起来是C99标准的F附录(例如,在F.9.44中指定了1**NaN)。 - jedwards
11
522页的轻松睡前阅读材料。 - wim
2
相关链接:https://bugs.python.org/issue15996 - 0j**math.nan => pow(0j, complex(float('nan'))). - Caramiriel
3
简短回答:Python 开发人员花时间修复了浮点数 ** 运算的边缘情况,但没有详细查看复数的复杂 pow 边缘情况。在一个采用 IEEE 754 双精度标准的系统上,浮点数使用普通的 ** 遵循各种标准(IEEE 754-2008、C99 附录 F 等)。复数的 ** 从未正确修复特殊值和边缘情况。 - Mark Dickinson
显示剩余7条评论
1个回答

6
引用这篇问题,该问题引用了IEEE 754标准(参见维基百科)。
IEEE 754 2008年版规定pow(1,qNaN)和pow(qNaN,0)应该都返回1,因为无论使用静默NaN的其他内容是什么,它们都会返回1。
有关详细信息,请参见IEEE 754 2008第56页: pow(x, ±0)对于任何x(甚至是零、静默NaN或无穷大)都是1 pow(±0, y)是±∞,并且对于y为奇数,会发出divideByZero异常
因此,推理似乎是无论指数中的数字k是什么,1^k = 11^Nan也应该是1。为什么这种推理是合理的(我确信它是),我需要进一步挖掘。
个人认为这很有道理 - 在数学中不存在Nan,只是我们的浮点表示无法处理它(或者,Nan是“计算量太大,这是某个数字,但不确定是哪个数字”)。因此,1^Nan可以是任意幂次的1(而不是非数字的1),但由于答案始终为1,因此只有定义1^Nan为1才有用。

我确实能理解这是有道理的。但是0j**math.nan呢? - Aguy
@Aguy:我认为这是一个错误,因为0 ** float('nan') = nan。 - zw324
那看起来像是非法分发的IEEE 754的PDF。 :-( - Mark Dickinson
@MarkDickinson:看起来像课堂资料,所以我认为它可能是合法的——如果你确定它是非法的,请随意将其编辑掉。不过,无论如何,这总是只需要谷歌一下就行了。 - zw324

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接