l'essentiel est invisible pour les yeux

Sunday, November 11, 2007

[Javascript] 64bit Number型を上位32bitと下位32bitに分割

JavascriptのNumber型は、倍精度64bitフォーマット IEEE 754型(double-precision 64-bit format IEEE 754 values)です。Javascriptでは、64ビット演算はできないので、上位32ビットと下位32ビットにわけて計算しないといけません。また、Math.pow(2, 55)など大きな数を扱う時には誤差も発生するので別途内部表現を設けて対応しないといけません。

パフォーマンスの犠牲を払っていますが、
上位32ビットと下位32ビットに変換します。


Number.prototype.rdHi = function() {
var b = this.toString(2);
return parseInt(b.slice(0,b.length-32), 2) || 0x0;
};
Number.prototype.rdLo = function() {
var b = this.toString(2);
return parseInt(b.slice(Math.max(b.length-32, 0), b.length), 2);
};
console.log(0x03ffffffff.rdHi() & 0xffffffff); // => 3
console.log(0xffffffffff.rdHi() & 0xffffffff); // => 255
console.log(0x01ffffffff.rdLo()); // => 4294967295
console.log(0x01ffffffff.rdLo() & 0xffffffff); // => -1


注意しなければいけないのは、最上位ビットは符号ビットだと言う事。最後の結果は、0xffffffffではなく、-1になります。32bit値を何かしらのフラグとして利用する場合は、最上位ビットを考慮したロジックを組む必要があります。

Number型(64bit)を利用する場合速度とメモリ消費量のトレードオフとなります。
例を挙げれば、ボードゲームを実装する際のデータ構造として一般的なBit Boardならば、次のどちらかの戦略をとる事になるかもしれません。
  • 64bit値を下位32bitと上位32bitの二要素として配列に持つ
  • 64bit変数で保持して、実行時に上記のメソッドを適用する。

一つ目は、メモリ消費量が多くなりますが配列から何かしらの操作を実行する時のコストは低くなり、二つ目はメモり消費量は減らせるが実行時のコストが大きくなります。

P.S
2の53乗以上のデータも扱えるように、倍精度でも誤差がでないNumber型を実装していたら似たようなライブラリがたくさんあったので中断。きちんと調べてから実装するべきだった。