78

重複の可能性:
JavaScript の数学は壊れていますか?

なぜ JS はこの単純な計算を台無しにするのでしょうか?

console.log(.1 + .2)  // 0.3000000000000004
console.log(.3 + .6)  // 0.8999999999999999

最初の例は正しい結果より大きく、2 番目の例は小さくなっています。???!! これをどのように修正しますか?操作を実行する前に、常に小数を整数に変換する必要がありますか? 追加することだけを心配する必要がありますか (* と / は私のテストでは同じ問題を抱えているようには見えません)?

私は答えを求めて多くの場所を調べました。一部のチュートリアル (ショッピング カート フォームなど) は、問題が存在しないふりをして値を追加するだけです。教祖は、さまざまな数学関数の複雑なルーチンを提供したり、JS が「うまくいかない」と述べたりしていますが、私はまだ説明を見ていません。

4

5 に答える 5

44

これは 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数値の表示方法を細かく制御できる機能を試すことができます。

于 2010-08-09T10:38:23.533 に答える
22

浮動小数点ガイドから:

0.1 + 0.2 などの数値を足して 0.3 にならず、代わりに 0.30000000000000004 のような奇妙な結果が得られるのはなぜですか?

内部的に、コンピューターは 0.1、0.2、0.3 などの数値を正確に表すことができない形式 (2 進浮動小数点) を使用しているためです。

コードがコンパイルまたは解釈されると、「0.1」はすでにその形式の最も近い数値に丸められているため、計算が行われる前であっても小さな丸め誤差が発生します。

このサイトには、詳細な説明と、問題を解決する方法 (および、問題があるかどうかを判断する方法) に関する情報があります。

于 2010-08-09T10:31:13.390 に答える
8

This is not a javascript only limitation, it applies to all floating point calculations. The problem is that 0.1 and 0.2 and 0.3 are not exactly representable as javascript (or C or Java etc) floats. Thus the output you are seeing is due to that inaccuracy.

In particular only certain sums of powers of two are exactly representable. 0.5 = =0.1b = 2^(-1), 0.25=0.01b=(2^-2), 0.75=0.11b = (2^-1 + 2^-2) are all OK. But 1/10 = 0.000110001100011..b can only be expressed as an infinite sum of powers of 2, which the language chops off at some point. Its this chopping that is causing these slight errors.

于 2010-08-09T10:28:50.320 に答える
5

すべての10進値を正確にバイナリで表すことができるわけではないため、これはすべてのプログラミング言語で正常です。すべてのコンピューター科学者が浮動小数点演算について知っておくべきことを参照してください

于 2010-08-09T10:23:47.600 に答える
1

それは、コンピューターが浮動小数点数を処理する方法と関係があります。あなたはここでそれについてもっと読むことができます:http://docs.sun.com/source/806-3568/ncg_goldberg.html

于 2010-08-09T10:22:32.187 に答える