9

Python 2 有两种整数数据类型intlong,并根据需要自动在它们之间进行转换,尤其是为了避免整数溢出。

我正在用 Python 模拟 C 函数,想知道是否有标准方法可以重新启用整数溢出。对于随机数,我用过

overflow_point = maxint + 1
if value > overflow_point:
    value -= 2 * overflow_point

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

4

5 回答 5

11

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

  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
于 2011-10-14T17:32:23.253 回答
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 中可能会看到的错误。如果要编写一个 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()
于 2013-01-09T20:37:22.047 回答
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
于 2011-10-14T17:46:23.863 回答
3

我不知道有一种方便的方法可以在本地执行此操作,因为它通常不被认为是一个问题,所以它不是 python 开发人员想要构建的东西。我认为你这样做的方式很好。您甚至可以继承int内置类型并覆盖__add__(),__sub__()等运算符方法以包含您的功能,但这可能是矫枉过正。

于 2011-10-14T17:18:13.613 回答
0

使用 NumPy(用 C 语言编写并公开本机机器级整数)。NumPy 有以下整数类型:

有符号整数:

  • np.int8
  • np.int16
  • np.int32

无符号整数:

  • np.uint8
  • np.uint16
  • np.uint32

例如(注意它在整数值 127 之后溢出):

import numpy as np

counter = np.int8(0)
one = np.int8(1)

for i in range(130):
    print(type(counter), counter)
    counter = counter + one

例如,在任何时候,您都可以使用 just 转换回 Python 整数int(counter)

于 2020-09-03T02:04:13.647 回答