可能性のある複製:
JavaScriptの数学は壊れていますか?
JSがこの単純な数学を台無しにするのはなぜですか?
console.log(.1 + .2) // 0.3000000000000004
console.log(.3 + .6) // 0.8999999999999999
最初の例は正しい結果よりも大きく、2番目の例はより小さくなっています。 ??? !!これをどのように修正しますか?操作を実行する前に、常に小数を整数に変換する必要がありますか?追加することだけを心配する必要がありますか(*および/はテストで同じ問題を抱えていないようです)?
私は多くの場所で答えを探しました。一部のチュートリアル(ショッピングカートフォームなど)では、問題が存在しないと想定し、値を加算するだけです。グルは、さまざまな数学関数に複雑なルーチンを提供するか、またはJSが合格すると「悪い仕事をします」と言いますが、まだ説明がありません。
これはJSの問題ではなく、より一般的なコンピューターの問題です。浮動小数点数はすべてを10進数で適切に格納することはできません。なぜなら、それらは2進数でデータを格納するからです。例:
0.5 is store as b0.1
but 0.1 = 1/10 so it's 1/16 + (1/10-1/16) = 1/16 + 0.0375
0.0375 = 1/32 + (0.0375-1/32) = 1/32 + 00625 ... etc
so in binary 0.1 is 0.00011...
しかし、それは無限です。ある時点でコンピューターを停止する必要がある場合を除きます。したがって、この例で0.00011で停止すると、0.1ではなく0.09375になります。
とにかくポイントは、それは言語ではなくコンピューターに依存しているということです。言語に依存するのは、数字の表示方法です。通常、言語は数値を許容可能な表現に丸めます。どうやらJSはそうではありません。
そのため、あなたがしなければならないこと(メモリ内の数値は十分に正確です)は、JSにテキストに変換するときに数値を「適切に」丸めるように伝えることです。
sprintf
関数を試して、数値の表示方法を細かく制御できます。
から 浮動小数点ガイド :
なぜ0.1 + 0.2のような数字がナイスラウンド0.3に加算されず、代わりに0.30000000000000004のような奇妙な結果が得られますか?
内部的には、コンピューターは0.1、0.2、0.3などの数値を正確に表現できない形式(2進浮動小数点)を使用するためです。
コードがコンパイルまたは解釈されると、「0.1」はその形式で最も近い数値に既に丸められているため、計算が行われる前でも小さな丸め誤差が生じます。
このサイトには、詳細な説明と問題の修正方法に関する情報(および、それが問題であるかどうかを判断する方法)があります。
これはjavascriptのみの制限ではなく、すべての浮動小数点計算に適用されます。問題は、0.1および0.2および0.3がjavascript(またはCまたはJavaなど)浮動小数点数として正確に表現できないことです。したがって、表示される出力はその不正確さによるものです。
特に、2の累乗の特定の合計のみが正確に表現可能です。 0.5 = = 0.1b = 2 ^(-1)、0.25 = 0.01b =(2 ^ -2)、0.75 = 0.11b =(2 ^ -1 + 2 ^ -2)はすべて問題ありません。ただし、1/10 = 0.000110001100011..bは、2の累乗の無限の合計としてのみ表現でき、言語はある時点で切り捨てます。これらのわずかなエラーの原因となっているこのチョッピング。
すべての10進値を正確にバイナリで表現できるわけではないため、これはすべてのプログラミング言語で正常です。 すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと を参照してください
コンピューターが浮動小数点数を処理する方法に関係しています。詳細については、こちらをご覧ください: http://docs.Sun.com/source/806-3568/ncg_goldberg.html