【问题标题】:Overflowing ints in pythonpython中的整数溢出
【发布时间】:2014-05-25 18:33:19
【问题描述】:

我正在将一段 Ian Bell 的 Elite 从 C 转换为 Python。 C (ab) 使用 16 位整数,会溢出。 Python 使用神奇的 Python 整数,但它没有。这是个问题。

我可以只定义一个class UInt16:(更新:或使用 ctype 内置的 UInt16),它的行为就像我想要的那样,但是我必须“强制”整个程序中的每个数字都是 @987654322 @。有什么方法可以告诉我的口译员“嘿,你知道Int 吗?好吧,我希望你在每个你通常使用其中之一的地方都使用这个类。”

或者,如果做不到这一点,是否有另一种简单的方法可以实现整数溢出?

【问题讨论】:

  • 这里的正确答案是“不要滥用整数”。只需手动实现“如果大于 2^16-1,则手动减去 2^16-1”。当然,这将意味着相当多的代码更改,但我认为为了可读性和定义的行为这是值得的。
  • 提示:如果数字大于 2^16-1,type(huge_number) 将返回 'long'(魔法整数)。
  • 使用 ctypes 中的 16 位整数
  • @slugonamission 你可能想使用模数,比如n%(2**16)。但是 Jonathon 是正确的,ctypes 的 uint16 应该可以工作。
  • @RoyIacob:Python 3 中不再区分常规整数和长整数。现在它们都是ints。

标签: c python-3.x porting integer-overflow


【解决方案1】:

简短回答:无法如您所愿覆盖默认整数行为。


更长的答案:

首先,我们可以看到 Python 中存在几种 16 位无符号整数的实现:

  1. 内置库ctypes 16 位无符号整数可用作c_uint16
  2. Numpy 库还包含unint16
  3. 实现您自己的 uint16 数据类型(使用运算符重载等)

我们是否可以使用这些或其他一些数据类型来覆盖 Python 中的默认整数的问题比较棘手。

假设用户使用int 方法在程序中创建所有整数。如果是这种情况,那么我们可以包装 int 方法来创建无符号整数而不是常规整数:

from ctypes import c_uint16
_int = int

def int(x):
    return c_uint16(x)

例如下面的代码就可以正常工作:

a = int(1)

我们可以检查:

>>> type(a)
<class 'ctypes.c_ushort'>

问题来了:

b = 1

在这种情况下,int 方法没有被调用,而是b 被简单地赋值为1。我们希望做的是也覆盖这种行为,但不幸的是it is not possible

【讨论】:

  • 不是答案。我正在寻找一种方法让 Python 使用 uint16s 代替普通整数,而无需在每次使用数字时都明确说明。
【解决方案2】:

AFAIR 这是不可能的。你想monkey-patch内置类型,即impossible in python

扩展版

整数文字(1,而不是 int("1"))始终是来自 builtins/__builtins__ 模块的 int 类型(取决于 python 版本)。您想要做的基本上是将unint16 上的所有方法复制到 int 类(因为方法只是函数类型的属性)。在这种情况下,在您声明 1 的每个地方,您都会得到一个 int 类型的对象,其行为就像 unint16

这在 python 中是不可能的。我想底层实现正因为如此而变得更容易,但这背后有更深层次的逻辑。

int 是核心类之一,如liststrobjectsetdicttuple 等。假设有人创建了非常方便的库,几乎每个人都会采用。如果您曾经使用过 Java,那么想象一下对 Apache Commons 或 Spring 的影响。几乎每个重要的人都会使用它,因为这些东西可以加快开发速度。现在,假设有人创建了 fork - 在他的公司内部使用,说他这样做是为了保持代码库稳定 - 有一小段代码,改变了内置 object 的行为,因此它向他发送了一些关键数据.他可以骗取数百万用户的私人数据(地址,然后他将出售,密码等等)。令人毛骨悚然的场景,对吧?

现在,这似乎不太真实,但是如果您让最终用户评估 python 脚本会怎样?您可能已经见过像 gedit 之类的文本编辑器或带有内置 python shell 的音乐播放器(Rhythmbox),它们提供程序内部的接口。现在,soemone,以某种方式将object 行为的更改注入您的机器。另一个令人毛骨悚然的场景。

这些是我想到的例子,我真的不记得 python 的创建者对它说了什么 - 这就是我提供进一步讨论的链接的原因。

有点跑题了——这实际上可能会导致一些优秀的库(“this”的意思是“允许在 builtins 上进行猴子修补”)。想象一下猴子修补所有 bultins 以便它们存储在某个多处理管理器中。您实际上获得了基于多处理的 java 风格的多线程,并且可以以某种方式避免 GIL。当然,还有很多其他原因说明这不是很好(例如,“多线程的错觉不是多线程”),但我发现它对于简单的日常桌面脚本很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 2014-01-24
    • 2014-06-08
    • 1970-01-01
    相关资源
    最近更新 更多