测试JavaScript中的舍入错误

时间:2013-07-19 19:40:38

标签: javascript jquery biginteger rounding-error

如何在JavaScript中确定数字是否太大(如果执行数学运算会导致舍入错误)。

例如,我有一个格式化百分比的函数。如果它无法正确格式化传入的值,我希望它返回与传入的值完全相同的值。

function formatPercent(x, decimals) {
     var n = parseFloat(x);                 // Parse (string or number)
     if ($.isNumeric(n) === false) {
         return x;                          // Return original if not a number
     } else {
         return n.toFixed(decimals) + '%';  // Return formatted string
     }
 };

alert(formatPercent(276403573577891842, 2)); // returns 276403573577891840.00%

由于格式化这么大的数字是一个极端情况并且没有预期,我宁愿只返回传入的数字。舍入错误开始之前的限制是多少?我将如何检查它们? / p>

更新:

What is JavaScript's highest integer value that a Number can go to without losing precision?表示精度最高可达+/- 9007199254740992.我正在测试是否需要检查以确保安全失败并返回未修改的传入值。

4 个答案:

答案 0 :(得分:1)

如果您始终将x作为字符串传递,则可确保没有舍入错误。问题是276403573577891842在解析数字文字时正在向右舍入,但如果使用字符串,则永远不会发生。试着这样做:

function formatPercent(x, decimals) {
    if(typeof x != "string" && typeof x != "number") return x;
    x = x+"";//convert to string if it is a number
    var r = /^(?:(\d+)(\.\d*)?|(\d*)(\.\d+))$/;// RegExp for matching numerical strings
    return x.replace(r, function(match, int, dec){
        if(decimals>0){
            int = (typeof int == "string"?int:"");//if passed string didn't have integers
            dec = (typeof dec == "string"?dec:".");//if passed string didn't have decimals
            while(dec.length-1<decimals) dec += "0";//pad zeroes until dec.length-1==decimals
            return int+dec.slice(0,decimals+1)+"%";//in case dec.length-1>decimals
        }
        int = (typeof int == "string"?int:"0");//if passed string didn't have integers
        return int+"%";
    });
    // Return formatted string or original string conversion if no match found
}

alert(formatPercent("276403573577891842", 1));// returns 276403573577891842.0%
alert(formatPercent("276403573577891842.55", 1));// returns 276403573577891842.5%
alert(formatPercent("276403573577891842.55", 0));// returns 276403573577891842%
alert(formatPercent(".55", 1));//returns .5%
alert(formatPercent(".55", 0));//returns 0%
alert(formatPercent(276403573577891842, 1));// returns 276403573577891840.0%
alert(formatPercent("this is not a number", 2));// returns this is not a number
alert(formatPercent({key:"not number or string"}, 2));// returns the object as it was

即使formatPercent在传递数字的情况下仍然失败,这将防止传递字符串的舍入错误。请注意这不是不正确的,因为它失败的唯一情况是当一个太大的数字被硬编码为参数时。

答案 1 :(得分:0)

function formatPercent(x, decimals) {
     var n = parseFloat(x);                 // Parse (string or number)
     if ($.isNumeric(n) === false) {
         return x;                          // Return original if not a number
     } else {
         var d = Math.pow(10, decimals)
         return (Math.round(n * d) / d).toString() + "%";
      }
 };

如果是.00

,使用舍入将丢弃小数

答案 2 :(得分:0)

这是我过去常常捕捉的too big or too small integers

function getSafeNumber(x) {
     var n = parseFloat(x);    // Parse and return a floating point number
     if ($.isNumeric(n) === false || 
         n >= 9007199254740992 || 
         n <= -9007199254740992) {
         return false;         // Not numeric or too big or too small
     } else {
         return n;             // return as number
     }
 };

答案 3 :(得分:-1)

由于no

的内部表示,不超过9个quardbillion将导致此类错误