5

エッジケースのシナリオと思われるものがあります。値4.015を小数点以下 2 桁に四捨五入しようとする4.01と、期待される代わりに常に4.02. .015これは、小数部分を含むすべての数値で一貫して発生します。

JS でかなり一般的な方法を使用して丸めます。

val = Math.round(val * 100) / 100;

問題は 100 を掛けたときに始まると思います。浮動小数点の不正確さにより、この値は切り上げではなく切り捨てられます。

var a = 4.015,                // 4.015
    mult = a * 100,           // 401.49999999999994 (the issue)
    round = Math.round(mult), // 401
    result = round / 100;     // 4.01 (expected 4.02)

フィドル: http://jsfiddle.net/eVXRL/

を丸めようとすると、この問題は発生しません4.025。の期待値4.03は戻ります。.015それは(これまでのところ)の問題だけです。

これをエレガントに解決する方法はありますか?もちろん、そのケースを1回限り探して.015処理するというハックがありますが、それは間違っているようです!

4

4 に答える 4

2

浮動小数点数は実数ではなく浮動小数点数です。

実数は無限にありますが、それらを表すビット数は有限であるため、必要な正確な数を浮動小数点システムで表すことができない場合、丸め誤差が発生することがあります。

したがって、浮動小数点数を扱うときは、念頭に置いていたのとまったく同じ数には ならないことを考慮する必要があります。
正確な数が必要な場合は、精度の高いライブラリを使用する必要があります。通常は、固定小数点やシンブリック表現を使用します。

詳細については、ウィキペディアのページe と、この (少し複雑ですが重要な) 記事を参照してください: すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと

于 2013-08-09T08:49:33.827 に答える
0

正規表現を使用して数字を抽出および置換し、必要なものを取得できます。

val = (val + "").replace(/^([0-9]+\.[0-9])([0-9])([0-9]).*$/, function(whole, head, lastdigit, followup) {
    if(followup >= 5) {
        return head + ("" + (parseInt(lastdigit) + 1));
    }else return head + lastdigit;
});

それ以外の場合は使用できますval = val.toFixed(2)が、特定の値 4.015 は 4.01 を返します (4.0151 は「期待される」として 4.02 を返します)。

于 2013-08-09T09:23:21.957 に答える