web-dev-qa-db-ja.com

Pythonでlongの符号付き整数値を取得するにはどうすればよいですか?

Lvがlong値を格納し、マシンが32ビットの場合、次のコード:

iv = int(lv & 0xffffffff)

マシンのintの代わりにlong型のivを返します。

この場合、(signed)int値を取得するにはどうすればよいですか?

23
Paul Oyster
import ctypes

number = lv & 0xFFFFFFFF

signed_number = ctypes.c_long(number).value
29
Raony Barrios

あなたは高水準のスクリプト言語で作業しています。本来、実行しているシステムのネイティブデータタイプは表示されません。このようなコードでは、ネイティブの署名付き整数にキャストすることはできません。

値が32ビットの符号付き整数に変換されることがわかっている場合(プラットフォームに関係なく)、単純な計算で変換を実行できます。

iv = 0xDEADBEEF
if(iv & 0x80000000):
    iv = -0x100000000 + iv
15
Glenn Maynard

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
9
gengkev

これを提案できますか:

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)
8
BreizhGatch

structライブラリを使用して、そのような値を変換できます。それは醜いですが、うまくいきます:

from struct import pack, unpack
signed = unpack('l', pack('L', lv & 0xffffffff))[0]
6
Tupteq

迅速で汚い解決策(私の場合、xが32ビットを超えることはありません)。

if x > 0x7fffffff:
    x = x - 4294967296
1
Rob Milne