13

我想将一个值表示为 64bit signed long,这样大于(2**63)-1的值表示为负数,但是 Pythonlong具有无限精度。我有没有“快速”的方法来实现这一目标?

4

4 回答 4

13

你可以使用ctypes.c_longlong

>>> from ctypes import c_longlong as ll
>>> ll(2 ** 63 - 1)
c_longlong(9223372036854775807L)
>>> ll(2 ** 63)
c_longlong(-9223372036854775808L)
>>> ll(2 ** 63).value
-9223372036854775808L

如果您确定目标机器上的 a 将是 64 位宽,那么这实际上只是一个选项。signed long long

编辑: jorendorff为 64 位数字定义一个类的想法很有吸引力。理想情况下,您希望尽量减少显式类创建的数量。

使用c_longlong,您可以执行以下操作(注意:仅限 Python 3.x!):

from ctypes import c_longlong

class ll(int):
    def __new__(cls, n):
        return int.__new__(cls, c_longlong(n).value)

    def __add__(self, other):
        return ll(super().__add__(other))

    def __radd__(self, other):
        return ll(other.__add__(self))

    def __sub__(self, other):
        return ll(super().__sub__(other))

    def __rsub__(self, other):
        return ll(other.__sub__(self))

    ...

这样一来,结果ll(2 ** 63) - 1确实会9223372036854775807。但是,这种构造可能会导致性能损失,因此根据您想要做什么,定义一个像上面这样的类可能不值得。如有疑问,请使用timeit.

于 2009-11-19T16:32:07.913 回答
13

你可以使用numpy吗?它有一个 int64 类型,完全符合您的要求。

In [1]: import numpy

In [2]: numpy.int64(2**63-1)
Out[2]: 9223372036854775807

In [3]: numpy.int64(2**63-1)+1
Out[3]: -9223372036854775808

与 ctypes 示例不同,它对用户是透明的,并且它是用 C 编码的,因此它比在 Python 中滚动您自己的类要快。Numpy 可能比其他解决方案更大,但如果您正在进行数值分析,您会很高兴拥有它。

于 2009-11-20T00:28:00.163 回答
3

最快的方法可能是自己将结果截断为 64 位:

def to_int64(n):
    n = n & ((1 << 64) - 1)
    if n > (1 << 63) - 1:
        n -= 1 << 64
    return n

您当然可以定义自己的数字类型,每次执行任何算术运算时都会自动执行此操作:

class Int64:
    def __init__(self, n):
        if isinstance(n, Int64):
            n = n.val
        self.val = to_int64(n)

    def __add__(self, other):
        return Int64(self.val + other)

    def __radd__(self, other):
        return Int64(other + self.val)

    def __sub__(self, other):
        return Int64(self.val - other)

    ...

但这并不是特别“快速”实施。

于 2009-11-19T16:30:22.643 回答
1

看看 ctypes 模块,它用于从 python 调用外部 DLL/库。有一些数据类型对应于 C 类型,例如

c_longlong 类

于 2009-11-19T16:31:37.663 回答