2009-11-19 92 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可能比其他解決方案更大,但如果您正在進行數值分析,您會欣賞它。