Python type long vs C 'long long'
I would like to represent a value as a 64bit signe开发者_运维百科d long
, such that values larger than (2**63)-1
are represented as negative, however Python long
has infinite precision. Is there a 'quick' way for me to achieve this?
You could use 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
This is really only an option if you know for sure that a signed long long
will be 64 bits wide on the target machine(s).
Edit: jorendorff's idea of defining a class for 64 bit numbers is appealing. Ideally you want to minimize the number of explicit class creations.
Using c_longlong
, you could do something like this (note: Python 3.x only!):
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))
...
In this way the result of ll(2 ** 63) - 1
will indeed be 9223372036854775807
. This construction may result in a performance penalty though, so depending on what you want to do exactly, defining a class such as the above may not be worth it. When in doubt, use timeit
.
Can you use numpy? It has an int64 type that does exactly what you want.
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
It's transparent to users, unlike the ctypes example, and it's coded in C so it'll be faster than rolling your own class in Python. Numpy may be bigger than the other solutions, but if you're doing numerical analysis, you will appreciate having it.
The quickest thing is probably to truncate the result to 64 bits yourself:
def to_int64(n):
n = n & ((1 << 64) - 1)
if n > (1 << 63) - 1:
n -= 1 << 64
return n
You can of course define your own numeric type that automatically does this every time you do any sort of arithmetic operation:
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)
...
but that is not particularly "quick" to implement.
Have a look at the ctypes module, it is used to call foreign DLLs/libraries from python. There a some data types that correspond to C types, for example
class c_longlong
精彩评论