Mac和Linux上不同的numpy溢出行为

quhf5bfb  于 2023-10-19  发布在  Mac
关注(0)|答案(1)|浏览(93)

我在Mac和Linux上遇到了不同的溢出行为,使用相同版本的numpy。MWE:

import numpy as np
arr = np.arange(0, 2 * 4e9, 1e9, dtype=float)
print(arr.astype(np.uint32))
print(np.__version__)

Mac(Python 3.9.13):

array([         0, 1000000000, 2000000000, 3000000000, 4000000000,
        705032704, 1705032704, 2705032704], dtype=uint32)
'1.22.4'

Linux(Python 3.9.7):

array([         0, 1000000000, 2000000000, 3000000000, 4000000000,
                0,          0,          0], dtype=uint32)
'1.22.4'

我更喜欢预期翻转的“Mac”行为(而不是强制溢出值为0),所以我想知道如何为Linux版本修复这个问题。

uidvcgyl

uidvcgyl1#

我相信这是由于numpy的底层C实现,它可能会触发未定义的行为,这是由用于numpy的linux和mac发行版的编译器不同地处理的。
看看cast float to unsigned int in C with gcc,它处理类似的主题,我们还可以看到link to the C standard,它在第51页上声明
6.3.1.4真实的浮点数和整数
1当一个真实的浮点类型的有限值被转换为一个整数类型而不是_Bool时,小数部分被丢弃(即,该值被向零截断)。如果整数部分的值不能用整数类型表示,则行为是未定义的。
一种可能性是,我猜你在编译自己的numpy版本时尝试不同的编译器,并检查行为。另外,由于您想要翻转行为,您可以尝试先转换为宽度较大的无符号整数类型,然后再转换为宽度较小的无符号整数类型,因为无符号整数转换总是会进行翻转
6.3.1.3有符号和无符号整数
1当整数类型的值被转换为_Bool以外的另一个整数类型时,如果该值可以用新类型表示,则该值不变。
2否则,如果新类型是无符号的,则通过重复增加或减去新类型中可以表示的最大值的一个值来转换值,直到值在新类型的范围内。

import numpy as np
arr = np.arange(0, 2 * 4e9, 1e9, dtype=float)
print(arr.astype(np.uint64).astype(np.uint32))
print(np.__version__)

相关问题