我想将一个值表示为 64bit signed long
,这样大于(2**63)-1
的值表示为负数,但是 Pythonlong
具有无限精度。我有没有“快速”的方法来实现这一目标?
问问题
37880 次
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 回答