Lvがlong値を格納し、マシンが32ビットの場合、次のコード:
iv = int(lv & 0xffffffff)
マシンのintの代わりにlong型のivを返します。
この場合、(signed)int値を取得するにはどうすればよいですか?
import ctypes
number = lv & 0xFFFFFFFF
signed_number = ctypes.c_long(number).value
あなたは高水準のスクリプト言語で作業しています。本来、実行しているシステムのネイティブデータタイプは表示されません。このようなコードでは、ネイティブの署名付き整数にキャストすることはできません。
値が32ビットの符号付き整数に変換されることがわかっている場合(プラットフォームに関係なく)、単純な計算で変換を実行できます。
iv = 0xDEADBEEF
if(iv & 0x80000000):
iv = -0x100000000 + iv
Pythonには任意の大きな整数があるため、問題は32ビットから無限のビット数に符号拡張することです。通常、符号拡張は、キャスト時にCPU命令によって自動的に行われます。 Pythonのほうが、たとえばCの場合よりも難しいです。
遊んでみたところ、BreizhGatchの関数に似たものが見つかりましたが、条件付きのステートメントは必要ありません。 n & 0x80000000
は、32ビットの符号ビットを抽出します。次に、-
は同じ32ビット表現を保持しますが、それを符号拡張します。最後に、拡張符号ビットがn
に設定されます。
def toSigned32(n):
n = n & 0xffffffff
return n | (-(n & 0x80000000))
Bit Twiddling Hacks は、おそらくより一般的に機能する別のソリューションを提案しています。 n ^ 0x80000000
は32ビットの符号ビットを反転します。次に、- 0x80000000
は反対のビットを符号拡張します。それについて考えるもう1つの方法は、最初は負の数が正の数の上にあるということです(0x80000000
で区切られています)。 ^
は位置を入れ替えます。次に、-
は負の数を0未満にシフトします。
def toSigned32(n):
n = n & 0xffffffff
return (n ^ 0x80000000) - 0x80000000
これを提案できますか:
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)
structライブラリを使用して、そのような値を変換できます。それは醜いですが、うまくいきます:
from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
迅速で汚い解決策(私の場合、xが32ビットを超えることはありません)。
if x > 0x7fffffff:
x = x - 4294967296