0

基本的に私の質問は: 130.0 ではなく 130.00000000000003 として値を取得するのはなぜですか?

ボンネットの下にあるすべてを出力しただけで、十分に明確であることを願っています。文字列/フロートが原因である可能性が最も高いことはわかっていますが、解決方法はわかりません。

parseFloat() 、 parseFloat().toFixed(1) 、 parseFloat().round(1) を試しましたが、それでも.00000000000003を取得し続けます。いつもではありませんが、時々。

コード :

// ... 'cost' will be passed as a parameter to the function 

 totalBudget = parseFloat(document.getElementById('currentBudget').value);// e.g value ='4' 

 ni = parseFloat(totalBudget);
 cost = (cost).toFixed(1);
 alert("totalBudget " + totalBudget + "\nni " + ni + "\ncost " + cost);
 ni += parseFloat(cost);
 alert("ni " + ni);

 alert('\nni= ' + ni + '\ntotalBudget= ' + totalBudget + '\ncost=' + cost);

 var playerCost = parseFloat(document.getElementById('playerCost' + vTemp).value);
 playerCost = (playerCost).toFixed(1);
 alert('playerCost= ' + playerCost);
 alert('\nNow will subtract ');
 ni -= playerCost;
 alert('\nAfter Subtraction');
 alert('\nni= ' + ni + '\nplayerCost= ' + playerCost);


alert('-------'+
'\ncurrBudget= '+totalBudget+
'\nnew budget ni= '+ni+
'\nPlayer#:vTemp= '+vTemp+
'\nCurr player cost= '+playerCost+
'\nNew players cost= '+cost +
"\nParseFloat(playerCost)for curr player= "+parseFloat(playerCost));

出力:

 // If cost = 7.2 and playerCost= 7.1. Notice all floating values are super fine. 
    totalBudget 129.8
    ni 129.8
    cost 7.2

    totalBudget 129.8
    ni 129.8
    cost 7.2


    ni= 137
    totalBudget= 129.8
    cost=7.2

    plaerCost= 7.1

    Now will subtract 
    After Subtraction


    ni= 129.9
    playerCost= 7.1


    -------
    currBudget= 129.8
    new budget ni= 129.9
    Player#:vTemp= 8
    Curr player cost= 7.1
    New players cost= 7.2
    ParseFloat(playerCost)for curr player= 7.1

ページを更新せずに、Web サイトで別の操作を行います

出力:

// If cost = 7.3 and playerCost= 7.2. Notice floating points are totally not fine. 
totalBudget 129.9
ni 129.9
cost 7.3

ni 137.20000000000002

ni= 137.20000000000002
totalBudget= 129.9
cost=7.3

plaerCost= 7.2

Now will subtract 

After Subtraction

ni= 130.00000000000003
playerCost= 7.2

-------
currBudget= 129.9
new budget ni= 130.00000000000003
Player#:vTemp= 8
Curr player cost= 7.2
New players cost= 7.3
ParseFloat(playerCost)for curr player= 7.2

すると「予算オーバーです。選手を変えてください!」と出ます。エラー原因 130.00000000000003 > 130.0

4

3 に答える 3

2

プログラミング言語で (2 進) 浮動小数点を使用して「お金の計算」を行おうとすると、そのような運命に陥ります。浮動小数点には、小数ではなく 2 進数の小数が含まれるため、必然的にこのような異常が発生します。

toFixed()浮動小数点数を文字列に変換することに注意してください。それは本当にあまり役に立ちません。

編集— コメントは、浮動小数点形式が必ずしもバイナリ浮動小数点形式ではないことを正しく指摘しています。古い IBM メインフレーム (おそらく現在の z シリーズ マシン) は、基数 16 の指数と (おそらく) 基数 16 の仮数を使用していたと思います。しかし、今日では、IEEE-754 形式は (良くも悪くも) かなり普遍的であり、x86 マシンで使用される形式です。GPU は (必ずしも、32 ビット NVidia 浮動小数点はかなり近いと思います) すべてが IEEE-754 ではありませんが、私が知っているものはすべてバイナリ浮動小数点システムです。(そして、具体的には、言語の定義により、JavaScript は 2 進浮動小数点です。)

もう一度編集— Eric Postpischil が下のコメントで教えてくれます :-)

于 2012-11-02T14:03:32.920 に答える
2

これはやり過ぎかもしれませんが、 BigDecimalを試してください。浮動小数点は精度の高い計算には適していません。また、JavaScript にはそれを処理する組み込みの「10 進数」型がありません。

また、精度がそれほど問題にならない場合は、toPrecision()メソッドを試してください。要らない部分だけ切り取ります。

var a = 1.000000000000005;
var b = a.toPrecision(6); //returns a string
var c = parseFloat(b); //returns a number
alert(b); // shows 1.000000;
alert(c); // shows 1;

編集:実際には問題ないはずです

function roundFloat(input, prec) {
    return parseFloat(input.toFixed(prec));
}

丸めが必要な数値に使用します。

于 2012-11-02T14:12:47.770 に答える
0

有効な小数点以下が 1 桁ある場合は、10 を掛けて整数に切り捨て、それを比較します。

var budget = 130.00000000000003;
var c1 = Math.round(budget * 10);
var c2 = Math.round(130 * 10);

if (c1 > c2)
    do_something;
于 2012-11-02T14:22:53.557 に答える