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 の仕様をかなり参考にしましたよ。