質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

4回答

20540閲覧

【python3】16進数の8byteデータをbit単位で取り出したい/1byteのデータを合体させて4byteにしたい

退会済みユーザー

退会済みユーザー

総合スコア0

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2017/04/13 01:46

こんにちは。

プログラミング初心者です。
以前teratailで整数長のものを1byteづつ取り出す際のコードを教えて頂きました。

python3

1i = 1500 2print('big') 3b = i.to_bytes( 4, byteorder='big') 4print(b[0]) #=1 5print(b[1]) #=5 6print(b[2]) #=0 7print(b[3]) #=0

今回は16進数の8byteデータを1byteづつに分け
それを1bit単位の0or1に分割したいのですが、
うまくいきません・・・

↓ダメな例

python3

1i = 1500 2print('big') 3b = i.to_bytes( 4, byteorder='big') 4print(b[0]) #=0 5print(b[1]) #=0 6print(b[2]) #=5 7print(b[3]) #=dc 8 9b8_2 = format(b[3],'08b') 10print(b8_2) #=11011100 11 12b8_bit = b8_2.to_bytes( 8, byteorder='big') 13print(b8_bit[0]) 14print(b8_bit[1]) 15print(b8_bit[2]) 16print(b8_bit[3]) 17print(b8_bit[4]) 18print(b8_bit[5]) 19print(b8_bit[6]) 20print(b8_bit[7])

また1byte毎に分けたデータを再度もとに戻す際は
「+」でも「&」でもうまくいかないのですが、どのようにすればよいのでしょうか・・・

python3

1i = 1500 2print('big') 3b = i.to_bytes( 4, byteorder='big') 4print(b[0]) #=0 5print(b[1]) #=0 6print(b[2]) #=5 7print(b[3]) #=dc 8b_s = b[0] + b[1] + b[2] + b[3]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

今回は16進数の8byteデータを1byteづつに分け
それを1bit単位の0or1に分割したいのですが、

単純にビット演算を行ったらよいのでないでしょうか

Python

1i = 1500 2b = i.to_bytes(4, byteorder='big') 3print(b[3]) 4for i in range(8): 5 print((b[3]>>i) & 1)

また1byte毎に分けたデータを再度もとに戻す際は

int.from_bytes() をご使用ください
https://docs.python.jp/3/library/stdtypes.html#int.from_bytes

Python

1num = int.from_bytes([0,0,5,220], byteorder='big', signed=False) 2print(num)

投稿2017/04/13 02:27

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/04/13 03:38

print((b[3]>>i) & 1) の &1は1bit目を表示という意味ですか?
magichan

2017/04/13 04:21

はい。論理演算の&ですので1bit目以外はマスクされます。 ですので、 「(b[3]>>i) で i ビット右にシフトさせた結果の 1bit目を取り出す」 という動作になります。
退会済みユーザー

退会済みユーザー

2017/04/17 08:57

丁寧にありがとうございました。 どの方も分かりやすかったので一番早いmagichanさんをベストアンサーとします。
guest

0

###1つめ:1byteづつに分けそれを1bit単位の0or1に分割したい

次のように list 関数をつかうことで1文字ずつばらしてリストに格納することができます。

python

1b8_bits = list(b8_2)

2つめの:1byte毎に分けたデータを再度もとに戻す

byteは16進数を2ケタずつ格納したものですので、算数的に考えれば次のように計算しますよね。

python

1b[3] + b[2] * (16 ** 2) + b[1] * (16 ** 4) + b[0] * (16 ** 6)

ただプログラム的には不恰好ですので、for ループや関数などを使ってうまく実装してください。

投稿2017/04/13 02:31

miyahan

総合スコア3095

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/04/17 08:56

丁寧にありがとうございました。 無事実装できそうです。
guest

0

バイト→ビット列に変換する処理を関数にしてみました。
バイトデータを元の数値に戻すのは、magichanさんの回答でいけると思います。

Python

1# byte -> bitの(実際には 0 or 1 のintを格納した)リストを返す 2def toBits( byte): 3 bits = [] 4 for shift in reversed(range(8)): # 上位桁からリスト追加するため 7 -> 0 に 5 bit = byte >> shift & 0x01 # 右シフトして指定桁のbit値を得る 6 bits.append(bit) 7 return bits 8 9# 8byteデータ 10i = 0x01020304FFFEFDFC 11bytes = i.to_bytes( 8, byteorder='big') 12# 確認表示 13for b in bytes: 14 bits = toBits(b) # ビットのリスト 15 print("0x%02X=%s" % (b,bits))

参考:整数とビット列の相互変換

投稿2017/04/13 04:41

can110

総合スコア38234

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/04/17 08:59

実装に組み込みました。 丁寧にありがとうございます。
guest

0

formatにやらせる方法も。

python3

1>>> a = 1500 2>>> bits = list(map(int, '{:b}'.format(a))) 3>>> print(bits) 4[1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0] 5>>> 6>>> import ast 7>>> ast.literal_eval('0b' + ''.join(map(str, bits))) 81500 9>>>

うーん、ちょっと邪道でした。
負の値を扱おうとするとすんなりいきません。

投稿2017/04/13 04:33

編集2017/04/13 04:35
sharow

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2017/04/17 08:58

丁寧にありがとうございます。 構文は少し難易度が高そうですが、挑戦してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問