为啥“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 【问题描述】:我对@987654321@ 的计算结果为np.nan
而不是np.inf
感到有些失望,因为这是正常除法的情况。
我想念 nan
比 inf
更好的选择有什么原因吗?
【问题讨论】:
这可能是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 而不是无穷大?的主要内容,如果未能解决你的问题,请参考以下文章