在Python中模拟整数溢出

bra*_*ese 7 python ctypes integer-overflow

蟒2具有两个整数数据类型intlong,并自动将它们之间作为转换必要,特别是为了避免整数溢出.

我在Python中模拟C函数,我想知道是否有重新启用整数溢出的标准方法.对于nonce,我已经习惯了

overflow_point = maxint + 1
if value > overflow_point:
    value -= 2 * overflow_point
Run Code Online (Sandbox Code Playgroud)

是否有更标准的方法来做同样的事情?

NPE*_*NPE 9

我认为基本的想法是合理的,但需要一些调整:

  1. 你的函数没有溢出sys.maxint+1,但它应该;
  2. sys.maxint 单次操作可以超过几次;
  3. 下面的负值-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
Run Code Online (Sandbox Code Playgroud)


Noc*_*wer 8

此函数应将您的数字转换为硬件整数.根据您的应用程序,您可能需要在操作的每个阶段之间应用此功能.

def correct(value, bits, signed):
    base = 1 << bits
    value %= base
    return value - base if signed and value.bit_length() == bits else value
Run Code Online (Sandbox Code Playgroud)

以下快捷方式函数可以派上用场将值"转换"到适当的范围:

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)
)
Run Code Online (Sandbox Code Playgroud)

作为如何使用它们的示例,可以再现一个可能在C中看到的错误.如果要使用字节来编写for循环以打印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()
Run Code Online (Sandbox Code Playgroud)


小智 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
Run Code Online (Sandbox Code Playgroud)