0

私は常にJavaでコーディングしており、最近JavaScript(正確にはnode.js)でコーディングを始めました。私を夢中にさせていることの 1 つは、10 進数の加算演算です。

次のコードを検討してください

var a=0.1, b=0.2, c=0.3;
var op1 = (a+b)+c;
var op2 = (b+c)+a;

驚いたことに、私は見つけましたop1 != op2!console.logging op1 と op2 は以下を出力します:

console.log(op1); 0.6000000000000001
console.log(op2); 0.6

これは意味がありません。JavaScript は単純に算術規則を無視できないため、これはバグのように見えます。誰かがなぜこれが起こるのか説明してもらえますか?

4

4 に答える 4

3

これは浮動小数点エラーのケースです。

浮動小数点数で正確に表現できる小数は、分母が 2 のべき乗である整数分数として記述できるものだけです。

たとえば、0.5 は 1/2 と表記できるため、正確に表すことができます。0.3 できません。

この場合、変数と式の丸め誤差が適切に組み合わされて、最初のケースではエラーが発生しましたが、2 番目のケースでは発生しませんでした。

どちらの方法もバックグラウンドで正確に表されるわけではありませんが、値を出力すると、16 桁の精度に丸められます。1 つのケースでは、わずかに大きい数値に丸められ、別のケースでは、期待値に丸められました。

あなたが学ぶべき教訓は、正確な値を持つ浮動小数点数に決して依存してはならないということです。特に算術を行った後はそうです。

于 2012-04-26T17:39:48.923 に答える
0

フロートを使用する場合は、比較する前に数値の精度を設定することをお勧めします。

(0.1 + 0.2).toFixed(1) == 0.3

ただし、いくつかのケースでは、toFixedはブラウザ間で同じように動作しません。toFixedの修正は次のとおりです。

http://bateru.com/news/2012/03/reimplementation-of-number-prototype-tofixed/

于 2012-04-26T18:21:25.717 に答える
0

これは JavaScript の問題ではありませんが、フロートを使用する場合のすべてのプログラミング言語での標準的な問題です。サンプル番号 0.1、0.2、および 0.3 は、0.1 = 1/(2*5) などのように除数 5 が含まれているため、有限小数として表すことはできませんが、反復小数として表すことはできません。除数 2 のみで小数を使用する場合 (a=0.5、b=0.25、c=0.125 など)、すべて問題ありません。

于 2012-04-26T17:48:42.350 に答える
0

これは、すべての浮動小数点数を 2 進数で正確に表現できるわけではないために発生します。

すべての数値に何らかの数値を掛けます (たとえば、小数点以下 2 桁の場合は 100)。

次に、より大きな結果に対して計算を行います。

計算が終わったら、最初にかけたのと同じ係数で割ります。

http://jsfiddle.net/SjU9d/

a = 10 * a;
b = 10 * b;
c = 10 * c;

op1 = (a+b)+c;
op2 = (b+c)+a;

op1 = op1 / 10;
op2 = op2 / 10;
于 2012-04-26T17:55:20.307 に答える