2007年07月04日
JavaScript で Number 型の数値を2進数表現してみる
先日の 四則演算を JavaScript で実装する の関連エントリ。
デバッグの過程で、数値を2進数で表示したくなったので実装してみた。
ソースコード
ワンライナー版。
function dump_int(i){var s="";while(i){s=(i&1)+s;i>>>=1}return s}
整形したらこうなる。
function dump_int(i) { var s = ""; while(i) { s = (i & 1) + s; i >>>= 1; } return s; }
>>> が符号を考えずに右シフトする演算子だそうだ。今回、このビット演算子で遊ぶまで、こんな演算子があることすら知らなかった。
Firebug で確認してみた
>>> function dump_int(i){var s="",c=-1;while(c){s=(i&1)+s;i>>>=1;c>>>=1}return s} >>> dump_int(0) "" >>> dump_int(1) "1" >>> dump_int(2) "10" >>> dump_int(3) "11" >>> dump_int(0x1000) "1000000000000" >>> dump_int(-1) "11111111111111111111111111111111" >>> dump_int(-2) "11111111111111111111111111111110" >>> dump_int(-3) "11111111111111111111111111111101"
出力の最大桁数が 32bit なのは、ビット演算の前に ToInt32 という内部関数が呼ばれて 32bit に切り詰められるから。
桁数をそろえるバージョン
桁数がそろってなくて見にくい場合は、こう改造すればよい。
>>> function dump_int2(i){var s="",c=-1;while(c){s=(i&1)+s;i>>>=1;c>>>=1}return s} >>> dump_int2(3) "00000000000000000000000000000011"
c = -1 として while(c){c >>>= 1;} のループを回すことにより、ビット数の回数だけ while のループが回るようにしている。
toString(2)
ところで、これとは別に Number.prototype.toString() に 2 を渡すことで2進数表示することもできる。今回作った dump_int とはちょっと異なっていて面白い。
>>> (0).toString(2) "0" >>> (1).toString(2) "1" >>> (2).toString(2) "10" >>> (-1).toString(2) "-1" >>> (-2).toString(2) "-10"
マイナスの値を渡したときの挙動が明らかに違う。というのも、Number 型は 64bit の浮動小数点であり、符号部に 1bit が割かれている。
というわけで、負数を toString(2) すると - がつくのは Number の内部に符号部があるから、と考えると納得がいく。
Number 形が浮動小数点ということは、小数を toString(2) することもできたりする。
>>> (2.25).toString(2) "10.01"
まとめ
- 自作 dump_int は 32bit までの数にしか対応できない
- toString(2) は 64bit の浮動小数点の範囲を全てカバーできる
比べてみると dump_int がいい所なしに見えるが、先日の 四則演算を JavaScript で実装する を作るときには役立ったんですよ、っと。
あ、そうそう、今回は ECMA-262 3rd edition の仕様をかなり参考にしましたよ。