关于numpy.int32与int的Python处理问题



在编写一个简单的Fibonacci脚本时,我发现Python处理numpy.int32的方式与处理常规整数的方式有些"奇怪"。

有人能帮我了解这种行为的原因吗?

使用Fibonacci代码如下,利用缓存显著加快速度;

from functools import lru_cache
import numpy as np
@lru_cache(maxsize=None)
def fibo(n):
if n <= 1:
return n
else:
return fibo(n-1)+fibo(n-2)

如果我定义了一个Numpy数组来计算(使用np.arange(,那么在n=47之前,一切都很好,然后事情就开始失控了。另一方面,如果我使用一个常规的python列表,那么这些值都是正确计算的

您应该能够看到与以下内容的区别;

fibo(np.int32(47)), fibo(47)

它应该回来(至少对我来说是这样(;

(-1323752223, 2971215073)

显然,针对numpy.int32输入的计算出现了非常错误的情况。现在,我可以通过在计算其他内容之前在fibo函数中插入一行"n=int(n("来解决这个问题,但我不明白为什么这是必要的。

我也试过np.int(47(而不是np.int32(47(,发现前者效果很好。然而,使用np.arange创建数组似乎默认为np.int32数据类型。

我已经尝试过删除缓存(我不建议你尝试——大约需要2个小时才能计算到n=47(——我也有同样的行为,所以这不是原因。

有人能为我提供一些见解吗?

感谢

Python的"整数具有无限精度";。这被构建到该语言中,使得新用户具有";少学一件事";。

虽然可能不是在你的情况下,或任何使用NumPy的人。这个库的设计目的是使计算尽可能快。因此,它使用了CPU体系结构非常支持的数据类型,例如32位和64位整数,这些整数整齐地放入CPU寄存器中,并具有不变的内存占用空间。

但是,我们又回到了处理溢出问题,就像在任何其他编程语言中一样。NumPy确实对此发出了警告:

>>> print(fibo(np.int32(47)))
fib.py:9: RuntimeWarning: overflow encountered in long_scalars
return fibo(n-1)+fibo(n-2)
-1323752223

这里我们使用的是一个有符号的32位整数。它能保持的最大正数是231-1=214783647。但第47个斐波那契数甚至比这个还要大,正如你计算的那样,它是2971215073。在这种情况下,32位整数溢出,我们得到-1323752223,这是它的两个补码:

>>> 2971215073 + 1323752223 == 2**32
True

它与np.int一起工作,因为这只是内置int的别名,所以它返回一个Python整数:

>>> np.int is int
True

有关更多信息,请参阅:原生int类型和numpy.int类型之间的区别是什么?

还要注意,整数参数的np.arange返回类型为np.int_的整数数组(与np.int不同,带有尾随下划线(。该数据类型依赖于平台,在Windows上映射为32位整数,但在Linux上映射为64位整数。

最新更新