为什么NumPy整数减法会产生float64?

14
在numpy中,为什么整数相减有时会产生浮点数?
>>> x = np.int64(2) - np.uint64(1)
>>> x
1.0
>>> x.dtype
dtype('float64')

当使用多种不同的整数类型(例如,有符号和无符号),且没有更大的整数类型可用时,似乎只会出现这种情况。


当我们用int32减去uint32时,不会复制相同的行为,但结果是int64。看起来像是numpy将其提升为浮点数,因为没有更大的整数类型。我找不到任何关于这种转换的文档。 - gout
2个回答

9
这是由numpy作者做出的明智决策。在决定结果类型时,只考虑操作数的类型,而不考虑它们的实际值。对于您执行的操作,存在结果超出有效范围的风险,例如,如果您减去一个非常大的uint64数字,则结果将不适合于int64。因此,安全选择是转换为float64,这肯定会符合结果(尽管可能精度降低)。
x = np.int32(2) - np.uint32(1)的示例进行比较。这总是可以安全地表示为int64,因此选择该类型。对于x = np.int64(2) - np.uint32(1)也是如此。这也将产生一个int64
另一种选择是遵循例如c规则,将所有内容转换为uint64。但这当然可能导致非常奇怪的溢出/下溢结果。
如果您想事先知道最终使用的类型是什么,请查看np.result_type()np.can_cast()np.promote_types()。阅读文档也可能有助于更好地理解问题。

1
除了有关这些特定函数的文档(对于更广泛的问题几乎没有什么可说的),您是否知道哪些部分的文档确实涵盖了这个问题?我已经搜索了一段时间,但并没有找到任何信息。 - Peter Hansen
1
不,它似乎相当稀疏。可以在问题的错误报告中找到更多信息和解释,例如 https://github.com/numpy/numpy/issues/7126,其中提供了更详细的说明。 - JohanL

3

我对NumPy不是专家,但我怀疑由于float64是能够适应int64uint64域的最小数据类型,所以减法操作将两个操作数都转换为float64,以便该操作始终成功。

例如,在使用int8uint8时:+128 - (256)无法适应int8,因为-128int8中无效,它只能回到-127。同样,在这种情况下我们不能使用uint8,因为我们显然需要符号。因此,我们采用浮点数/双精度数,因为它可以很好地适应两个方向。


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