スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Python:ビット演算

 こんばんは。今回もPythonです。

最近は、苺サーボ(PRS-40M)をPythonから制御しています。
昔はマイコンから制御して実験していたのですが、Pythonだと効率良く開発が進みます。
その時にハマった、C言語辺りからPythonに入った人が陥りやすい罠ついて書きます。

コマンド式サーボモータはコマンド生成や、データを読み込む時によくビット演算を用います。
負の値として苺サーボは二の補数表現を用いています。
これは1の負数である-1を表現するなら以下のようにな流れになります。

① ビット反転する
② 反転した数字から1を足す

これを実際にPythonで実行します。


>>> ~1 + 1
-1


正しそうな値が出てきました。

次に、苺サーボの現在位置を複合してみます。(苺サーボは現在位置を16bitのデータとして送ってくる。)
複合の手順は逆にたどり最後にマイナスを掛けます。
① 値から1引く
② ビットを反転する
③ 値に-1を掛ける(複合した値は正の数のため)

それでは実際に負の限界値である-3600(二の補数表現で61936)を複合します。


>>> ~(61936 - 1)
-61936


①と②を実行しただけでもうすでにおかしいです。
負の値になっています。何が問題なのでしょうか。
疑問としては桁数が不明なPythonでどのよにビット反転をしているのでしょうか?
二の補数表現は一番上位のビットを1にする決まりですが、一番上位とは変数のサイズが決まらないPythonでは表現できません。

そこでPythonではビット反転演算を以下のように定義しいるそうです。


-(値 + 1)


これなら納得です。最初の値が合って、現在位置の複合がうまく行かない理由がわかります。
実際には何が悪いのかわからずかなり戸惑いました。
C言語上がりの私には、こんな罠があるとは思いもしませんでした。

そこでビット反転はXORを使ってやることにします。


>>> -((61936 - 1) ^ 0xFFFF)
-3600


現在位置は16bitとわかっているので、0xFFFFでビット反転することが出来ます。



1111 0001 1111 0000 :-3600の二の補数表現
1111 0001 1110 1111 :-1した値

1111 1111 1111 1111 :0xFFFF

0000 1110 0001 0000 :XORした値(1がひとつだけあるところは1)


以上がビット演算の流れです。
Pythonではビット反転をするときはXORを使って反転するしかなさそうです。
知っていればハマりませんが、思い込むとなかなか抜けられなくて苦労しました。

今回は以上です。

2012/10/01 追記
せっかくなので、負値を二の補数表現に変換するプログラムも記述しておきます。
-3600という値を二の補数表現にします。


>>> p = -3600
>>> (-p ^ 0xFFFF) + 1
61936


これで上記の二の補数表現と同じになりました。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

月別アーカイブ
カテゴリ
FC2カウンター
最新コメント
リンク
最新トラックバック
検索フォーム
RSSリンクの表示
ブロとも申請フォーム

この人とブロともになる

QRコード
QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。