2017-02-08 3 views
4

私は単純に1.275.toFixed(2)を切り上げようとしていますが、私は1.28の戻り値が1.27ではなく期待していました。最後の桁は、以上 5に等しい場合、様々な計算と最も近い百に丸めるの簡単な方法を使用しtoFixed(2)で3進数のtoFixed(2)を使用する信頼できるJS丸めの数値

、それは切り上げなければなりません。

これはtoFixed(2)で動作しない場合はどうでしょうか? (1.275.toFixedは(2))1.28をオフに印刷し、ここで素早くスクリーンショットMacOSのクロームバージョン55.0.2883.95(64ビット)

enter image description here

+0

'はconsole.log(1.275.toFixed(2))試してみてください;'私は ' '1.28''を取得します。 –

+2

'1.275'はバイナリで周期的です。 –

+1

これは[ブラウザごとに異なるかもしれません](http://stackoverflow.com/questions/566564/math-roundnum-vs-num-tofixed0-and-browser-inconsistencies)、私はクロムで '1.27'を得ます – Liam

答えて

4

toFixed()方法があるかどうかを確認するにconsole.log

人々その理由はなぜですか(Álvaro González' answer参照)。現在のChromeとFirefoxの両方で

toFixed()を呼び出すと、次の一貫性のない結果が得られます。

35.655.toFixed(2) // Yields "36.66" (correct) 
35.855.toFixed(2) // Yields "35.85" (wrong, should be "35.86") 

MDNはreliable rounding implementationについて説明します。

// Closure 
(function() { 
    /** 
    * Decimal adjustment of a number. 
    * 
    * @param {String} type The type of adjustment. 
    * @param {Number} value The number. 
    * @param {Integer} exp The exponent (the 10 logarithm of the adjustment base). 
    * @returns {Number} The adjusted value. 
    */ 
    function decimalAdjust(type, value, exp) { 
    // If the exp is undefined or zero... 
    if (typeof exp === 'undefined' || +exp === 0) { 
     return Math[type](value); 
    } 
    value = +value; 
    exp = +exp; 
    // If the value is not a number or the exp is not an integer... 
    if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) { 
     return NaN; 
    } 
    // Shift 
    value = value.toString().split('e'); 
    value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp))); 
    // Shift back 
    value = value.toString().split('e'); 
    return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)); 
    } 

    // Decimal round 
    if (!Math.round10) { 
    Math.round10 = function(value, exp) { 
     return decimalAdjust('round', value, exp); 
    }; 
    } 
    // Decimal floor 
    if (!Math.floor10) { 
    Math.floor10 = function(value, exp) { 
     return decimalAdjust('floor', value, exp); 
    }; 
    } 
    // Decimal ceil 
    if (!Math.ceil10) { 
    Math.ceil10 = function(value, exp) { 
     return decimalAdjust('ceil', value, exp); 
    }; 
    } 
})(); 

// Round 
Math.round10(55.55, -1); // 55.6 
Math.round10(55.549, -1); // 55.5 
Math.round10(55, 1);  // 60 
Math.round10(54.9, 1);  // 50 
Math.round10(-55.55, -1); // -55.5 
Math.round10(-55.551, -1); // -55.6 
Math.round10(-55, 1);  // -50 
Math.round10(-55.1, 1); // -60 
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above 
// Floor 
Math.floor10(55.59, -1); // 55.5 
Math.floor10(59, 1);  // 50 
Math.floor10(-55.51, -1); // -55.6 
Math.floor10(-51, 1);  // -60 
// Ceil 
Math.ceil10(55.51, -1); // 55.6 
Math.ceil10(51, 1);  // 60 
Math.ceil10(-55.59, -1); // -55.5 
Math.ceil10(-59, 1);  // -50 
+0

パーフェクト、より信頼できる方法として私は何を使用すべきですか? – jQuerybeast

+1

ありがとうございます。私はそれを上のスニペットに取り除いた。 – jQuerybeast

4

1.275ベース10数が有限の桁数を持っていますが、時に周期的になり、塩基2に変換:

= 0b1.01000110011001100110011001100110011001100110011010 
     ^^^^ 

これは無限の桁数を持つため、任意の精度ライブラリ(数字を10進数で表すための数値として表現するのではなく、ライブラリを使用しない限り)を正確に表すことはできません。 JavaScriptの数値はパフォーマンス上の理由からこのようなライブラリを使用しません。

JavaScriptに到達すると、元の値は既に精度が失われているため、丸めても精度は向上しません。

0

ロビーの回答によると、MDNは、それゆえ私は1.281.275の3進数を丸めるの私の問題を解決するために、次のスニペットにそれをダウン剥奪、reliable rounding implementationを説明しています。 MacOSのにFF4、クロム55とSafari 10.0.3でテスト

function decimalAdjust(c,a,b){if("undefined"===typeof b||0===+b)return Math[c](a);a=+a;b=+b;if(isNaN(a)||"number"!==typeof b||0!==b%1)return NaN;a=a.toString().split("e");a=Math[c](+(a[0]+"e"+(a[1]?+a[1]-b:-b)));a=a.toString().split("e");return+(a[0]+"e"+(a[1]?+a[1]+b:b))}Math.round10||(Math.round10=function(c,a){return decimalAdjust("round",c,a)}); 

Math.round10(1.275, -2); 
関連する問題