2009年05月22日 15:00 [Edit]

javascript - には整数はない

違います。

javascriptで整数の変数を強制的に符号なし整数に変換する方法 ? ku
javascriptの整数は内部的には32bit intで扱われていて(Firefox3.1, Chrome0.2の場合)、演算の結果が0×80000000を超えると自動的に負の値になります。

事実はもっと驚くべきものです。


以下をご覧下さい。

puts = make_puts(document.getElementById('ttyp0'));

for (var n = 1; n <= 54; n++){
    puts(2, '**', n, ' - 1 = ', Math.pow(2, n) - 1);
}

2の32乗どころか、2の53乗まできちんと計算できていますが、54乗になったとたん、数字が変です。奇数でなければならないのに偶数になっています。

なぜこんなことになるかといえば、JavaScriptのNumberオブジェクトは、数値を常に浮動小数点で保持しているからです。そうなのです。JavaScriptには整数がないんです。整数が「ある」ように見えているのは、文字列にする時に小数点がないだけなのです。

ECMAScript Language Specification (HTML version)

4.3.20 Number Type

The type Number is a set of values representing numbers. In ECMAScript, the set of values represents the double-precision 64-bit format IEEE 754 values including the special "Not-a-Number" (NaN) values, positive infinity, and negative infinity.

確かにこれなら、整数が32bitではなく53bitまである理由も納得が行きます。

それでは、なぜ以下は「期待通り」に動くのでしょうか?

puts = make_puts(document.getElementById('ttyp1'));

for (var n = 1; n <= 54; n++){
    puts('(1', '<<', n, ') - 1 = ', (1 << n) - 1);
}

それは、ビット演算の時のみ、内部的に32bit整数に変換してから、演算が終わった後また浮動小数点に戻しているからです。C的にいえば、一旦 signed int にキャストしているだけなのです。

Arrayオブジェクトが実は配列ではなく、数値をキーとするただのオブジェクトなのと同様、JavaScriptにはこうした「あるように見せかけているけど、実はない」という落とし穴が結構あって、むしろ中級者以上ほどはまりやすいように感じます。

Dan the JavaScripter

Auxiliary Codes

make_puts = function(el){
    return function(){
        for (var i = 0, l = arguments.length; i < l; i++){
            el.appendChild(document.createTextNode(arguments[i]));
        }
        el.appendChild(document.createElement('br'));
    }
};

この記事へのトラックバックURL

この記事へのコメント
「整数」と「整数型」は混乱する初心者も多いので、「整数型はない」として頂いた方が良いかと…
1.0は「整数」ですから。IEEE doubleで表現されていたとしても。
Posted by shiro at 2009年05月22日 17:44