Python における整数のエンディアンネス
-
05-07-2019 - |
質問
私は、いくつかのデータを整数に保存し、それをビット単位で処理するプログラムに取り組んでいます。たとえば、48 という数字を受け取るとします。これを少しずつ処理します。一般に、整数のエンディアンは整数のマシン表現に依存しますが、Python は整数が常にリトルエンディアンであることを保証するために何かをしますか?それとも、C の場合と同様にエンディアンをチェックしてから、2 つのケースに対して別々のコードを記述する必要がありますか?
私のコードは Sun マシンで実行されており、現在実行されているマシンは Intel プロセッサを使用していますが、将来的にはビッグエンディアンであることがわかっている Sun プロセッサを搭載したマシンに切り替える必要があるかもしれないため、質問しました。
解決
パイソンの int
は、実行されるプロセッサと同じエンディアンを持ちます。の struct
このモジュールを使用すると、バイト BLOB を int に (その逆や、その他のデータ型も) 変換できます。 フォーマット文字列 選んで:でフォーマットを開始します @
または、ネイティブのエンディアンネス(およびネイティブサイズ - 他のすべてが標準サイズを使用する)、ネイティブの「〜」、 '<' for little-endian '>'または '!ビッグエンディアンのために。
これはビットごとではなく、バイトごとです。この文脈でビットごとの処理が何を意味するのか正確にはわかりませんが、同様に対応できると思います。
単純な場合の高速「一括」処理については、次のことも考慮してください。 配列 モジュール -- fromstring
そして tostring
メソッドは大量のバイトを高速に処理でき、 byteswap
このメソッドは、多数の項目 (配列全体) に対して、「他の」エンディアン (ネイティブから非ネイティブ、またはその逆) を再度迅速に取得できます。
他のヒント
データを「ビット単位」で処理する必要がある場合は、 bitstring
モジュールは役に立つかもしれません。プラットフォーム間のエンディアンにも対応できます(少なくとも最新のトランクビルドでは-数日中にリリースされる予定です)。
struct
モジュールは、プラットフォーム間のエンディアンを処理します。たとえば、これは整数1、2、3をネイティブエンディアンを使用して2つの「ショート」と1つの「ロング」(ほとんどのプラットフォームで2および4バイト)にパックおよびアンパックします。
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
プログラムでプラットフォームのエンディアンを確認するには、次を使用できます
>>> import sys
>>> sys.byteorder
&quot; big&quot;
または&quot; little&quot;
を返します。
いつチェックしますか
ビット単位の操作を行う場合、int inは、入力したintと同じエンディアンを持ちます。チェックする必要はありません。両方の言語afaikでバイトシーケンスとの間で変換を行う場合にのみ、この点に注意する必要があります。
Pythonでは、このためにstructモジュールを使用します。最も一般的なのはstruct.pack()およびstruct.unpack()です。
次のスニペットは、システムのデフォルトがリトルエンディアンであるかどうかを示します(そうでない場合はビッグエンディアンです)
import struct
little_endian = (struct.unpack('<I', struct.pack('=I', 1))[0] == 1)
ただし、これはビット演算子の動作には影響しません。システムのデフォルトのエンディアンに関係なく、 1&lt;&lt; 1
は 2
と等しくなります。