CodeIQで「はしれ!モード学園」という漫画が公開され、話題になってたので問題をやってみましたが、つまずいたのが浮動少数点の問題。
なので自分のためにも問題の解説をまとめておきます。
漫画:https://codeiq.jp/magazine/2015/10/30057/
問題:https://codeiq.jp/q/2378
問題
次のコードを実行した時に出力されるのは?
var i = 0;
var cnt = 0;
while (i < 1) {
cnt ++;
i += 0.1;
}
console.debug(cnt);
解答
私は深く考えず、すぐに「10」だと思ってしまいましたが、
答えは「11」でした。
考察
問題のコードでwhile文の中でiを出力するコードを追加して検証しました。
すると以下のようになります。
0.3のところもおかしいですが、、、
0.7のあとから誤差で少しずつずれが生じています。
丸め誤差
原因は丸め誤差というものです。
10進数0.1を2進数に変換すると、10進数では有限けたであるのに、2進数では無限小数(循環少数)となってしまいます。いま、小数点以下5桁までしか表現できないとすると、下記の式の編みかけ部分は表現できず、これにより、丸め誤差が発生します。
0.1 = 0.000110011……
(2進数)
編みかけ部分が表現できず丸められた値$=2^{-4}+2^{-5}=0.009375$
絶対誤差=|0.09375-0.1|=0.00625
これだけの誤差が生じます。
※これは例えなので、JavaScriptでこの誤差が生じているわけではありません