質問: 本当にちいさな質問なのですがJavascriptで ``` alert(19.4*50); ``` とすると「969.9999999999999」とでてきます。 けど、計算機で計算すると「970」と表示されます。。。 なぜ計算結果が異なるのか不明なのですがご存じの方いらっしゃればご教授おねがいします・・・。 すみません。私のブラウザー環境ですが IE:10 Chrome: 69.0.3497.100 です
回答: 基本的には PicoSushi さんの言われている事柄は間違っていないんですが、リンク先は主に10進数での有限精度の計算について書かれてあるものなので補足です。 JavaScriptでは、数値を64ビットの2進浮動小数点数で表しています。2進数では、10進表記で`19.4`となるような(人間から見たら)単純な値でも、計算機内で正確に表すことができず、無限に続く循環小数になってしまいます。 ``` 19.4 = (2進表記)10011.01100110011001100110011001100110011001100110011001... ``` これを64ビットに詰め込むため、64ビットの2進浮動小数点数では内部的にこんなことになっています。 ``` 0100000000110011011001100110011001100110011001100110011001100110 -^^^^^^^^^^^ ``` (`_`を付したところは符号(`0`がプラス)、`^^^`を付したところが指数部(小数点位置を表している)です。) 見比べてもらうと分かりますが、`0110`が無限に続くはずが途中で打ち切られています。無限に続く部分を有限に収める時に、単に切り捨てとせず四捨五入(2進法なんで零捨一入ですが)が起こるため`0`で終わるはずのところが`1`になっていることもあります。 とにかく、切り捨てにしろ切り上げにしろ無限に続く値を有限ビット数で表せば誤差が入ってきます。計算の中身によっては、2進数を10進表記に変換する場合にも四捨五入が入るので、たまたま小数点を含む計算でも10進数で計算した時と同じ結果が表示される時がありますが、本当にたまたまでしかありません。 元々誤差を含んでいる値を元に計算しているのですから、計算結果も誤差を含んでいます。上記の「たまたま」がうまく働かないとご質問にあるような結果が表示されることになります。 と言うわけで ### 数値として2進浮動小数点数が用いられる場合 * 定数を10進表記で表していても内部では2進数で処理される * 有限の2進数で小数を表した場合の計算は、常に誤差を伴いうる と言うことを覚えていただいた方が良いでしょう。 普通の計算機は「計算に10進法を使う」または「うまく四捨五入している」のどちらかの理由で、「970」と言う値が表示されているものと思われます。 ただ、「10進数型」と言うものが手軽に使える場合でも、答えが無限小数になるような場合には誤差が含まれることは PicoSushi さんの回答内にあるリンクの通りです。 計算機と同じような結果を得たかったら、あなたのコードでも「計算に10進法を使う」か「うまく四捨五入している」必要があります。