一个 Python 整数溢出的坑

众所周知,Python 的整数是不会溢出的,例如运行如下代码,Python 可以完整地计算出 $2^{100}$

1
2
print(2 ** 200)
# 1606938044258990275541962092341162602522202993782792835301376

但是,在执行以下代码时,发现整数却溢出了

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

result = 0
array = np.array([145, 124, 58])

for i in array:
result += i
result = result << 8

print(result)
# -1854129664

这是为什么呢?Python 的整数怎么会溢出呢?我们输出中间的计算过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import numpy as np

result = 0
array = np.array([145, 124, 58])

for i in array:
result += i
print(result)
result = result << 8
print(result, '\n')

# 输出结果:
# 145
# 37120
#
# 37244
# 9534464
#
# 9534522
# -1854129664

看来是在最后一步溢出的,难道是 Python 算错了吗?单独计算

1
2
print(9534522 << 8)
# 2440837632

可以看到,单独计算 9534522 << 8 的结果确是正确的。进一步调试,发现 result 的类型竟然是 int32 而不是 int

fig2

原来是因为 array 中的数据类型是 np.int32 ,因此变量 i 的类型也是 np.int32 ,在执行 result += i 后,int 类型与 np.int32 类型相加后结果被转成了 np.int32 这才出现了整数溢出。因此,只需将 i 的类型转为 int 就不会发生溢出了。修改前面的代码

1
2
3
4
5
6
7
8
9
10
11
import numpy as np

result = 0
array = np.array([145, 124, 58])

for i in array:
result += int(i) # 将 np.int32 转为 int
result = result << 8

print(result)
# 2440837632 没有出现溢出
原创技术分享,您的支持将鼓励我继续创作