在Python中模拟整数溢出
在Python 2中,有两种整数类型,分别是int
和long
,它们会根据需要自动转换,以避免整数溢出的问题。
我正在用Python模拟一个C语言的函数,想知道有没有标准的方法可以重新启用整数溢出。现在我用的是
overflow_point = maxint + 1
if value > overflow_point:
value -= 2 * overflow_point
有没有更标准的方法来做到这一点呢?
5 个回答
5
你的函数有没有用到除法或者右移位运算?如果没有的话,你就不需要担心在计算的每个阶段会出现溢出,因为你总是能得到“正确”的结果,结果会在2的32次方或2的64次方的范围内。返回结果之前(或者在进行除法或右移位运算之前),你可以用一些方法把结果调整回标准的整数范围,比如:
import sys
HALF_N = sys.maxint + 1
N = HALF_N * 2
def normalize(value):
return (value + HALF_N) % N - HALF_N
8
这个函数的作用是把你的数字转换成看起来像硬件整数的样子。根据你的应用需求,你可能需要在每一步操作之间都使用这个函数。
def correct(value, bits, signed):
base = 1 << bits
value %= base
return value - base if signed and value.bit_length() == bits else value
下面这些快捷函数可以帮助你把数值“转换”到合适的范围:
byte, sbyte, word, sword, dword, sdword, qword, sqword = (
lambda v: correct(v, 8, False), lambda v: correct(v, 8, True),
lambda v: correct(v, 16, False), lambda v: correct(v, 16, True),
lambda v: correct(v, 32, False), lambda v: correct(v, 32, True),
lambda v: correct(v, 64, False), lambda v: correct(v, 64, True)
)
举个例子,可能会在C语言中遇到一个bug。如果你用一个字节来写一个循环,打印出0到255的数字,这个循环可能会一直运行下去,永远不会结束。下面的程序就演示了这个问题:
#! /usr/bin/env python3
def main():
counter = 0
while counter < 256:
print(counter)
counter = byte(counter + 1)
def correct(value, bits, signed):
base = 1 << bits
value %= base
return value - base if signed and value.bit_length() == bits else value
byte, sbyte, word, sword, dword, sdword, qword, sqword = (
lambda v: correct(v, 8, False), lambda v: correct(v, 8, True),
lambda v: correct(v, 16, False), lambda v: correct(v, 16, True),
lambda v: correct(v, 32, False), lambda v: correct(v, 32, True),
lambda v: correct(v, 64, False), lambda v: correct(v, 64, True)
)
if __name__ == '__main__':
main()
13
我觉得这个基本想法是不错的,但需要一些调整:
- 你的函数在
sys.maxint+1
的时候不会溢出,但应该会; - 通过一次操作,
sys.maxint
可以被超过好几次; - 还需要考虑小于
-sys.maxint-1
的负值。
考虑到这些,我想出了以下内容:
import sys
def int_overflow(val):
if not -sys.maxint-1 <= val <= sys.maxint:
val = (val + (sys.maxint + 1)) % (2 * (sys.maxint + 1)) - sys.maxint - 1
return val