为啥“np.inf // 2”会导致 NaN 而不是无穷大?

Posted

技术标签:

【中文标题】为啥“np.inf // 2”会导致 NaN 而不是无穷大?【英文标题】:Why does “np.inf // 2” result in NaN and not infinity?为什么“np.inf // 2”会导致 NaN 而不是无穷大? 【发布时间】:2020-12-01 09:45:32 【问题描述】:

我对@9​​87654321@ 的计算结果为np.nan 而不是np.inf 感到有些失望,因为这是正常除法的情况。

我想念 naninf 更好的选择有什么原因吗?

【问题讨论】:

这可能是floor_divide 比单独执行这两个操作更有效。 我会说inf 将是整数除法的错误结果,因为inf 不是整数。现在nan 也不是整数,但至少它以某种方式表达了这样一个事实,即所提出的问题没有正确答案,即没有整数x 使得x*2 等于inf。无论如何,这就是我的看法。 @0x5453 - 你是对的。所以问题是为什么nan 也被认为是比inf 更好的选择? @sepp2k - 你会认为np.floor(np.inf) 导致np.inf 是正确的结果吗?你也可以声称这个问题没有正确的整数答案。 @phuclv:很确定 INF 除以除 INF 或 NaN 之外的任何值仍然是 +-INF。但这是常规除法,而不是地板除法; IDK 如果 IEEE-754 完全定义了该操作; C 没有它,而现实世界的 FPU 也没有。 (您可以将舍入模式设置为截断或朝向 -Inf 并仍然获得 Inf。) 【参考方案1】:

我将成为 just points at the C level 实施的人,而不会试图解释意图或理由:

*mod = fmod(vx, wx);
div = (vx - *mod) / wx;

看起来为了计算浮点数的divmod(当你只是do floor division时调用它)它首先计算模数并且float('inf') %2只有NaN才有意义,所以当它计算@987654327时@ 它以 NaN 结束,所以一切都传播 nan 剩下的路。

简而言之,由于地板除法的实现在计算中使用了模数,即NaN,所以地板除法的结果也是NaN

【讨论】:

如果这真的是实现浮点除法的 C 代码,它可能是正确的,但非常不令人满意。你真的只是把罐子踢到了路上。 是的,我承认,我非常希望看到更好的答案。然而,推理可能是“直到现在还没有人真正考虑过”,在这种情况下,恐怕这可能是唯一的答案。 为什么不只用一行将div = (vx - *mod) / wx; 中的*mod 替换为上面等号之后的部分? @rautamiekka 是计算模数和地板除法的源代码,它需要保留模数。 @TadhgMcDonald-Jensen 所以这个值以后会被重用?【参考方案2】:

楼层划分是根据模数定义的,两者都构成了 divmod 操作的一部分。

Binary arithmetic operations

楼层除法和模运算符通过以下方式连接 身份:x == (x//y)*y + (x%y)。楼层除法和模数也是 与内置函数 divmod() 连接:divmod(x, y) == (x//y, x%y).

对于x = inf 这个等价是不成立的——余数inf % y 是未定义的——使得inf // y 模棱两可。这意味着nan 的结果至少与inf 一样好。为简单起见,CPython actually only implements divmod and derives both // and % by dropping a part of the result — 这意味着 // 从 divmod 继承 nan

【讨论】:

【参考方案3】:

无穷大不是一个数字。例如,您can't even say 认为无穷大 - 无穷大为零。所以你会遇到这样的限制,因为 NumPy 是一个 numerical 数学包。我建议使用像 SymPy 这样的 symbolic 数学包,它可以使用无穷大处理许多不同的表达式:

import sympy as sp

sp.floor(sp.oo/2)
sp.oo - 1
sp.oo + sp.oo

【讨论】:

以上是关于为啥“np.inf // 2”会导致 NaN 而不是无穷大?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要将双精度值分配给双精度值?导致 NaN

为啥逻辑回归中更高的学习率会产生 NaN 成本?

为啥读数千分尺测量有时会返回 NaN?

AngularJS:为啥即使显示正确,我也会得到 NaN?

为啥在多维数据集中分配值时会产生nan?

为啥 NaN^0 == 1