この番号i = -6884376
があるとしましょう。符号なしの変数を参照するにはどうすればよいですか? Cの(unsigned long)i
のようなもの.
仮定:
(unsigned long)
によってmean符号なし32ビット整数、次に、2**32 (or 1 << 32)
を負の値に追加するだけです。
たとえば、これを-1に適用します:
>>> -1
-1
>>> _ + 2**32
4294967295L
>>> bin(_)
'0b11111111111111111111111111111111'
仮定#1は、-1を1ビットの固定文字列として表示することを意味し、仮定#2は、32を使用することを意味します。
ただし、隠された前提が何であるかを言うことはできません。たとえば、1の補数表現を念頭に置いている場合は、代わりに~
プレフィックス演算子を適用する必要があります。 Python整数は、無限に広い2の補数表現(通常の2の補数のように、無限の数の "符号ビット"を使用)を使用するという錯覚を与えるために懸命に働きます。
また、プラットフォームCコンパイラの機能を複製するには、ctypes
モジュールを使用できます。
>>> import ctypes
>>> ctypes.c_ulong(-1) # stuff Python's -1 into a C unsigned long
c_ulong(4294967295L)
>>> _.value
4294967295L
Cのunsigned long
は、このサンプルを実行したボックスではたまたま4バイトです。
Cキャストに相当する値を取得するには、ビット単位で適切なマスクを使用します。例えばunsigned long
が32ビットの場合:
>>> i = -6884376
>>> i & 0xffffffff
4288082920
または、64ビットの場合:
>>> i & 0xffffffffffffffff
18446744073702667240
ただし、Cの値は得られますが、符号付きの値であるため、後続の計算で負の結果が得られる可能性があり、マスクを適用して32または64をシミュレートする必要があることに注意してくださいビット計算。
Pythonはすべての数値を符号と大きさとして格納するように見えますが、ビット単位の演算は2の補数値で動作するように定義されているため、これは機能します。 Cは整数を2の補数で格納しますが、ビット数は固定です。 Pythonビット単位演算子は、2の補数の値に作用しますが、無限のビット数を持っているかのように動作します。 &
演算子は、1の左向きの文字列をゼロに変更し、C値に適合するビットのみを残します。
値を16進数で表示すると、これがより明確になる場合があります(32ビットまたは64ビットのいずれかに関心があることを示す式としてfの文字列に書き直しました)。
>>> hex(i)
'-0x690c18'
>>> hex (i & ((1 << 32) - 1))
'0xff96f3e8'
>>> hex (i & ((1 << 64) - 1)
'0xffffffffff96f3e8L'
Cの32ビット値の場合、正の数値は2147483647(0x7fffffff)まで、負の数値は-1(0xffffffff)から-2147483648(0x80000000)までの最上位ビットセットになります。マスクに完全に適合する値の場合、小さなマスクを使用して符号ビットを削除し、符号ビットを減算することにより、Pythonのプロセスを逆にすることができます。
>>> u = i & ((1 << 32) - 1)
>>> (u & ((1 << 31) - 1)) - (u & (1 << 31))
-6884376
または、64ビットバージョンの場合:
>>> u = 18446744073702667240
>>> (u & ((1 << 63) - 1)) - (u & (1 << 63))
-6884376
この逆プロセスでは、符号ビットが0の場合、値は変更されませんが、マスクサイズに収まらない値で開始するとそれらのビットはなくなるため、明らかに真の逆ではありません。
Pythonには組み込みの符号なし型がありません。数学演算を使用して、Cで取得する値を表すnew intを計算できますが、Python intの「符号なしの値」はありません。 Python intは整数値の抽象化であり、固定バイトサイズの整数への直接アクセスではありません。
struct
Python組み込みライブラリを使用できます。import struct
i = -6884376
print('{0:b}'.format(i))
packed = struct.pack('>l', i) # Packing a long number.
unpacked = struct.unpack('>L', packed)[0] # Unpacking a packed long number to unsigned long
print(unpacked)
print('{0:b}'.format(unpacked))
でる:
-11010010000110000011000
4288082920
11111111100101101111001111101000
dec_pack = struct.pack('>L', unpacked) # Packing an unsigned long number.
dec_unpack = struct.unpack('>l', dec_pack)[0] # Unpacking a packed unsigned long number to long (revert action).
print(dec_unpack)
でる:
-6884376
[NOTE]:
>
はBigEndian操作です。l
は長いです。L
は符号なしlongです。AMD64
アーキテクチャではint
とlong
は32ビットなので、それぞれi
とI
の代わりにl
とL
を使用できます。 。pythonで署名なしから署名済みに変換するためにabsを使用するだけです
a=-12
b=abs(a)
print(b)
出力:12
pythonには、intをunsigned intに変換する組み込み関数がありません。
>>> val = 9223372036854775807 (maximum value of int 64)
>>> type(val)
<type 'int'>
>>> val += 1
>>> type(val)
<type 'long'>
Valの値を1増やすと、符号付き64ビット整数の制限を超え、値がlongに変換されます。 Pythonが符号なし整数を使用または変換した場合、valはintのままでした。または、長くはありません。
符号付き整数は、ビット(通常は最上位ビット)で表され、正の数の場合は0、負の数の場合は1に設定されます。 val&0xffが実際に行うのは、valと0x000000ff(32ビットマシン上)です。つまり、符号付きビットは0に設定され、符号なしの値がエミュレートされます。
例:
>>> val = -1
>>> val & 0xff
255