日別アーカイブ: 2016-07-25

不可思議な論理積ビット演算

ビットについて

Bit

ビットとは情報の最小単位であり、オンかオフ、点灯か消灯、有か無、通電か切電、表か裏などのように二つの状態を表す情報量を言います。

1ビットで2通りの状態を表現できますが、ビットを連ねて組み合わせ4ビットならば16通り、8ビットでは256通り、16ビットでは65536通り、32ビットでは4294967296通りの状態を表現できます。

8bit

ビットを8個連ねた情報単位を1バイトと呼び、アルファベット、数字、特殊記号などをコード化して利用しています。

コンピューターにおいて切電か通電、N極かS極など2つの状態からなる2進数を記憶や演算に用いています。

ビット演算

数の演算において、代表的なものに加算、減算、乗算、除算の四則演算があります。コンピューターの黎明期では加算、減算、乗算に較べ、除算は1桁遅い実行時間がかかりました。そのため、除算命令をなるべく使わないことが推奨されていました。ある数を256で除しその余りを求めるには、255との論理積演算で求めるのが適切とされていました。

Status256

変数のサイズは32ビットに限ったことではありませんが、平均的な例を考えてみます。

上図のビット構成や式で分かるように、変数vを256で割ったときの余りはv%256;で求めることができます。

JavaScriptで同じような試みをしたところ、思わぬ深みに足を取られましたので、ことの顛末を記録することにしました。上の式でwには青部分の下8ビットはゼロになります。

論理積ビット演算と制御処理

ステータス変数
ステータス変数

プログラミングにおいて、処理を実行するとき、その状態をステータス変数に記憶させます。

曲線が描画中かそうでないかは1ビットあれば十分です。それ故、左図のように曲線ごとに割り当てます。今回は6,7,14,15ビットを使用し多くの曲線をサポートすることができます。

描画開始に描画中ビットをonにし、描画完了後にそのビットをoffにしさらに、描画完了ビットをonにします。

特定ビットをゼロにする方法

特定ビットをゼロにするには論理積演算子(&)を使います。
w = v & 0xffffff00; //32ビット変数vの下8ビットをゼロにし、変数wに代入します

文法エラーの例示

SyntaxError2

JavaScriptデバッガが出力するエラーメッセージは上に示したように、具体的でかつ発生個所を指摘してくれます。’;’にすべきところを’:’にして文法エラーになった例です。

エラーメッセージと発生個所
エラーメッセージと発生個所

しかし、時には白地に赤で示したような曖昧なメッセージになることもあり、加えて発生場所の数字がよくわかりません。

今回の全ソース行は283であり、437は何を示すのか不明です。次に明らかにエラーが起きるようにコードを修正してみました。

発生個所を突き止める
発生個所を突き止める

130行でエラーが起きるようにコードとして許されない文字を入れると発生個所の番号が420に変化しました。先の番号よりも17小さくなり、130+17=147行が文法エラーの原因かも知れないと判明しました。

0xffffff00は32ビットの値であり、変数64ビットの処理系では正しい動作となりえず文法エラーとして弾き飛ばしていると推測することができました。

機種依存

環境依存からの脱却

論理積演算を用いたコードはローカル環境では正常に動作することが多いですが、サーバーにアップロードすると文法エラーになり、非常に混乱します。”Uncaught SyntaxError: Invalid or Unexpected token”が出力されます。

JavaScriptのAND演算で誤動作することが多く、w = v & 0xffffff00;に目星を付けます。0xffffff00は32ビットの値であり、変数を32ビットとしたコードは環境依存であり適切ではありません。よって次のように変更します。

w = v & 0xffffff00; //変数を32ビット限定にしている

w = v – (v % 256); //環境依存を避けます

まとめ

ローカル環境で動作確認できれば、あとはアップロードするだけと甘く考えていたら大きな落とし穴に落ち込みました。環境に依存するコードは避けるべきという教訓を得ました。

AND3 今回、文法エラーが起きているとき、何故どこで起きているかを探る手掛かりの一つを紹介しました。参考になれば幸いです。

最後に愚痴をこぼすことが許されるならば、『ローカル環境でも環境に依存するコードは文法エラーとして弾き飛ばしてくれればよいのに』と言いたいです。