質問

ブール値の配列のコンパクトな表現が必要です、Pythonには組み込みのビットフィールド型がありますか、または別の解決策を見つける必要がありますか?

役に立ちましたか?

解決

Bitarray は、最近同様のニーズがあったときに見つけた最良の答えでした。これはC拡張(純粋なPythonであるBitVectorよりもはるかに高速)であり、実際のビットフィールドにデータを格納します(したがって、要素ごとに1バイトを使用するように見えるnumpyブール配列よりも8倍メモリ効率が高くなります)

他のヒント

主にビットフィールドに名前を付けて簡単に操作できるようにする場合、たとえば通信プロトコルで単一ビットとして表されるフラグを使用するには、 ctypes Pythonでctype構造体+ユニオンを適切に宣言するにはどうすればよいですか? -スタックオーバーフロー

たとえば、バイトの最下位4ビットを個別に処理するには、LittleEndianStructureで最下位から最上位に名前を付けるだけです。ユニオンを使用して、byteまたはintと同じデータへのアクセスを提供し、データを通信プロトコルの内外に移動できるようにします。この場合、flags.asbyteフィールドを介して行われます:

import ctypes
c_uint8 = ctypes.c_uint8

class Flags_bits(ctypes.LittleEndianStructure):
    _fields_ = [
            ("logout", c_uint8, 1),
            ("userswitch", c_uint8, 1),
            ("suspend", c_uint8, 1),
            ("idle", c_uint8, 1),
        ]

class Flags(ctypes.Union):
    _fields_ = [("b", Flags_bits),
                ("asbyte", c_uint8)]

flags = Flags()
flags.asbyte = 0xc

print(flags.b.idle)
print(flags.b.suspend)
print(flags.b.userswitch)
print(flags.b.logout)

4ビット(ここでは、最上位から印刷しましたが、印刷の際により自然に見えます)は、1、1、0、0、つまりバイナリの0xcです。

最近バージョン2.0に達した bitstring モジュールをご覧ください。 。 バイナリデータはバイト配列としてコンパクトに保存され、簡単に作成、変更、分析できます。

バイナリ、8進数、16進数、整数(ビッグエンディアンまたはリトルエンディアン)、文字列、バイト、フロート、ファイルなどからBitStringオブジェクトを作成できます。

a = BitString('0xed44')
b = BitString('0b11010010')
c = BitString(int=100, length=14)
d = BitString('uintle:16=55, 0b110, 0o34')
e = BitString(bytes='hello')
f = pack('<2H, bin:3', 5, 17, '001') 

その後、単純な関数またはスライス表記を使用してそれらを分析および変更できます。ビットマスクなどを心配する必要はありません。

a.prepend('0b110')
if '0b11' in b:
    c.reverse()
g = a.join([b, d, e])
g.replace('0b101', '0x3400ee1')
if g[14]:
    del g[14:17]
else:
    g[55:58] = 'uint:11=33, int:9=-1'

ビットポジションの概念もあります。そのため、便利な場合は、ファイルまたはストリームのように扱うことができます。プロパティは、ビットデータのさまざまな解釈を提供するために使用されます。

w = g.read(10).uint
x, y, z = g.readlist('int:4, int:4, hex:32')
if g.peek(8) == '0x00':
    g.pos += 10

さらに、標準のビット単位のバイナリ演算子、パック、アンパック、エンディアンなどのサポートがあります。最新バージョンはPython 2.7および3.x向けであり、純粋なPythonですが、メモリと速度の点でかなり適切に最適化されています。

ビット単位のバイナリ演算子!、<!> amp;、|、^、<!> gt; <!> gt ;、および<!> lt; <!> lt;を使用します。それらは非常にうまく機能し、基盤となるCに直接実装されます。通常、基盤となるハードウェアに直接実装されます。

各値を2のべき乗として表します。

testA = 2**0
testB = 2**1
testC = 2**3

次に、値をtrueに設定します:

table = table | testB

値をfalseに設定するには:

table = table & (~testC)

値をテストするには:

bitfield_length = 0xff
if ((table & testB & bitfield_length) != 0):
    print "Field B set"

これが意味をなさない場合は、16進数表現をもう少し詳しく調べてください。これは基本的に、組み込みCアプリケーションでもブールフラグを追跡する方法です(メモリが制限されている場合)。

BitVectorパッケージが必要な場合があります。 Pythonインストールには組み込まれていませんが、Pythonサイトで簡単に追跡できます。

現在のバージョンの

https://pypi.python.org/pypi/BitVector

NumPyには、ビットフィールドの作成に使用できる配列インターフェースモジュールがあります

ビットフィールドが短い場合、おそらく structモジュールを使用できます。それ以外の場合は、アレイモジュールを囲むラッパーをお勧めします。

また、ctypesモジュールには bitfields 、しかし私は自分で使ったことがない。 警告者

int(またはlong int)を使用してブールの配列(または整数のセット)として表現する場合は、 http://sourceforge.net/projects/pybitop/files/

ビットフィールドのlong intへの挿入/抽出を提供します。最上位または最下位の「1」ビットを見つけます。すべての1をカウントします。ビット反転;純粋なpythonではすべて可能ですが、Cでははるかに高速です。

scroll top