Si lv stocke une valeur longue et que la machine est 32 bits, le code suivant:
iv = int(lv & 0xffffffff)
résulte un iv de type long, au lieu de l'int de la machine.
Comment puis-je obtenir la valeur (signée) int dans ce cas?
import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
Vous travaillez dans un langage de script de haut niveau; par nature, les types de données natifs du système sur lequel vous exécutez ne sont pas visibles. Vous ne pouvez pas transtyper vers un fichier natif signé avec un code comme celui-ci.
Si vous savez que vous souhaitez convertir la valeur en un entier signé 32 bits, quelle que soit la plate-forme, vous pouvez simplement effectuer la conversion avec le calcul simple:
iv = 0xDEADBEEF
if(iv & 0x80000000):
iv = -0x100000000 + iv
Puis-je suggérer ceci:
def getSignedNumber(number, bitLength):
mask = (2 ** bitLength) - 1
if number & (1 << (bitLength - 1)):
return number | ~mask
else:
return number & mask
print iv, '->', getSignedNumber(iv, 32)
Vous pouvez utiliser struct library pour convertir de telles valeurs. C'est moche, mais ça marche:
from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
Le problème est essentiellement de signer une extension de 32 bits à ... un nombre infini de bits, car Python a des entiers arbitrairement grands. Normalement, l’extension de la signature se fait automatiquement par les instructions de la CPU lors de la conversion. Il est donc intéressant de noter que cela est plus difficile en Python qu’en C.
En jouant, j'ai trouvé quelque chose de similaire à la fonction de BreizhGatch, mais cela n'exige pas d'instruction conditionnelle. n & 0x80000000
extrait le bit de signe 32 bits; alors, le -
conserve la même représentation 32 bits mais le signe le étend; enfin, les bits de signe étendus sont définis sur n
.
def toSigned32(n):
n = n & 0xffffffff
return n | (-(n & 0x80000000))
Bit Twiddling Hacks suggère une autre solution qui fonctionne peut-être plus généralement. n ^ 0x80000000
retourne le bit de signe 32 bits; alors - 0x80000000
signera-étendra le bit opposé. Une autre façon de penser est qu’au départ, les nombres négatifs sont supérieurs aux nombres positifs (séparés par 0x80000000
); le ^
échange leurs positions; alors le -
décale les nombres négatifs en dessous de 0.
def toSigned32(n):
n = n & 0xffffffff
return (n ^ 0x80000000) - 0x80000000
Une solution rapide et sale (x n'est jamais supérieur à 32 bits dans mon cas).
if x > 0x7fffffff:
x = x - 4294967296