JavaScript おれおれ Advent Calendar 2011 – 13日目
JavaScriptに限った話じゃないんですけどね。
console.log(0.1 + 0.2 == 0.3); // => false
なんでかというと、現代のコンピューターの性質で、数値を2進数、つまり2の階乗の和で表現しようとするためです。
例えば0.5
は簡単ですね。2-1です。また0.25
は2-2ですから、0.75
は2-1+2-2という事になります。
ちなみにJavaScriptで階乗を扱う場合はMath.pow()
です。
console.log(Math.pow(2, -1)); // => 0.5 console.log(Math.pow(2, -2)); // => 0.25 console.log(Math.pow(2, -1) + Math.pow(2, -2)); // => 0.75
それでは0.1
はどう表せば良いでしょうか?
console.log(0.1.toString(2)); // => "0.0001100110011001100110011001100110011001100110011001101"
おわかり頂けるでしょうか、これ、循環小数になります。10進数でいうところの1/3 = 0.33333333…みたいなやつです。
ですので、0.1
は2進数の世界に生きるコンピューターでは正確に扱う事ができません。なので近似値で扱うのですが、実際の数値とはちょっとだけずれているので、計算を行うと変な結果になってしまったりするわけです。
こんなコードは危険です。
for (var i = 0.1; i < 1; i += 0.1) { console.log(i); }
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
ループカウンター実数ではなく整数を使うようにしましょう。
for (var i = 1; i < 10; i += 1) { console.log(i / 10); }
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9