long
より大きい値が負として表されるように、値を 64 ビットの signed として表現したいと思いますが(2**63)-1
、Pythonlong
の精度は無限です。これを達成するための「迅速な」方法はありますか?
4 に答える
あなたが使用することができます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
編集: 64ビット数のクラスを定義する というjorendorffのアイデアは魅力的です。理想的には、明示的なクラス作成の数を最小限に抑える必要があります。
を使用する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
ください。
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 は他のソリューションよりも大きいかもしれませんが、数値解析を行っている場合は、それがあるとありがたいでしょう。
おそらく最も簡単なのは、結果を自分で 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)
...
しかし、それは実装するのに特に「速い」わけではありません。
ctypesモジュールを見てください。これは、Pythonから外部DLL/ライブラリを呼び出すために使用されます。たとえば、C型に対応するいくつかのデータ型があります
クラスc_longlong