2009-11-19 106 views
11

我想将一个值表示为一个64位有符号的long,使得大于(2 ** 63)-1的值表示为负数,但Python long具有无限精度。是否有一个“快速”的方式来实现这一目标?Python类型长对C'long long'

回答

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 

这真是只有,如果你的选择确信在目标机器上signed long long将是64位宽。

编辑:jorendorff's idea定义一个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

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) 

    ... 

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

1

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

类c_longlong

10

你能使用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可能比其他解决方案更大,但如果您正在进行数值分析,您会欣赏它。

相关问题