Javascript toFixed不舍入

时间:2012-04-04 16:06:44

标签: javascript

我使用javascript绑定到一些复选框,toFixed(2)没有四舍五入。任何想法,为什么它不四舍五入?例如,如果该号码为859.385,则仅显示859.38而不是859.39

我还读过toFixed可以根据您使用的浏览器进行不同的循环,任何人都知道如何解决这个问题,以便我的javascript计算与我的php计算相匹配?

var standardprice = parseFloat($('#hsprice_'+this.id.split('_')[1]).val());
var price =  parseFloat($('#hprice_'+this.id.split('_')[1]).val());
var discount =  parseFloat($('#hdiscount_'+this.id.split('_')[1]).val());
var deposit =  parseFloat($('#hdeposit_'+this.id.split('_')[1]).val());

var currSprice = parseFloat($('#hTotalSprice').val());
var currPrice = parseFloat($('#hTotalPrice').val());
var currDiscount = parseFloat($('#hTotalDiscount').val());
var currDeposit = parseFloat($('#hTotalDeposit').val());

currSprice += standardprice;
currPrice += price;
currDiscount += discount;
currDeposit += deposit;

$('#lblTotalSprice').text('$'+addCommas(currSprice.toFixed(2)));
$('#lblTotalPrice').text('$'+addCommas(currPrice.toFixed(2)));
$('#lblTotalDiscount').text('$'+addCommas(currDiscount.toFixed(2)));
$('#lblTotalDeposit').text('$'+addCommas(currDeposit.toFixed(2)));

$('#hTotalSprice').val(currSprice.toFixed(2));
$('#hTotalPrice').val(currPrice.toFixed(2));
$('#hTotalDiscount').val(currDiscount.toFixed(2));
$('#hTotalDeposit').val(currDeposit.toFixed(2));

23 个答案:

答案 0 :(得分:28)

  

我还没有找到toFixed10错误的数字。还有其他人吗?

感谢blghis answer向我指出了Mozilla的toFixed10()方法。

使用它我想出了这个短的衬垫,这确实涵盖了这里提到的所有情况......

function toFixed( num, precision ) {
    return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision);
}

答案 1 :(得分:18)

我将其用作所有财务数据中的最佳舍入函数。您可以在所有有问题的数字上进行测试。 Javascript允许某种精度,所以我使用它来使几乎每个数字按预期舍入。

function roundTo(n, digits) {
        if (digits === undefined) {
            digits = 0;
        }

        var multiplicator = Math.pow(10, digits);
        n = parseFloat((n * multiplicator).toFixed(11));
        return Math.round(n) / multiplicator;
    }

答案 2 :(得分:14)

在Chrome中,toFixed()轮次:

859.385 ==> 859.38
859.386 ==> 859.39

当我查看the ECMAScript 5th edition specification for .toFixed()(第15.7.4.5节)时,我并没有看到它明确地描述了舍入,尽管它确实描述了一些可能与Chrome实施的内容相当晦涩的内容。

在我看来,如果你想用明确的舍入来控制它,那么你应该使用经常建议的解决方法:

var roundedNum = (Math.round( num * 100 ) / 100).toFixed(2);

这将保证您像以前一样获得可预测的舍入。

此处的演示演示:http://jsfiddle.net/jfriend00/kvpgE/

答案 3 :(得分:8)

与35.855一起尝试的另一个好数字是1.005

我不认为Robert Messerle的解决方案处理1.005

此处的舍入小数示例https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round $ revision / 1383484#Decimal_rounding将数字转换为指数表示法,似乎可以获得更好的结果。

我在这里创建了一个小提琴http://jsfiddle.net/cCX5y/2/,演示了上面的本地Robert Cyserle示例(称为toFixedB)和来自Mozilla文档的示例(称为toFixed10)。

我还没有找到toFixed10错误的数字。还有其他人吗?

答案 4 :(得分:7)

由于在javascripts的toFixed-function中,浮点数5不属于整数的上半部分,如果您有这样的数字,则给定的数字向下舍入:

859.385.toFixed(2) // results in 859.38

事实上你可能会附加尾随浮点数(零除外),如下所示:

859.3851.toFixed(2) // results in 859.39

因此,开发人员倾向于添加0.00000000001之类的数字,以使其适当舍入,并且不会意外更改数字的值。

所以我想出了一个函数,根据你想要修改浮点数的位数来添加这样的数字:

    // both parameters can be string or number
    function toFixed(number, decimals) {
        var x = Math.pow(10, Number(decimals) + 1);
        return (Number(number) + (1 / x)).toFixed(decimals)
    }
    toFixed(859.385, 2) //results in 859.39

答案 5 :(得分:6)

function roundup(num,dec){
    dec= dec || 0;
    var  s=String(num);
    if(num%1)s= s.replace(/5$/, '6');
    return Number((+s).toFixed(dec));
 }

 var n= 35.855
 roundup(n,2)

/ *返回值:(Number) 35.86 * /

答案 6 :(得分:3)

您可以使用Math.round()对数字进行舍入。如果你想要舍入到特定的小数点,你可以使用一点数学:

var result=Math.round(original*100)/100

答案 7 :(得分:2)

我今天遇到了同样的问题,甚至在其他答案中尝试建议我发现我仍然没有收到我预期的结果。最后,当我在运行此项目时使用AngularJS作为我当前的项目时,我想我检查AngularJS是否已经解决过相同类型的问题,而且确实已经解决了。这是他们使用的解决方案,对我来说非常适合:

function toFixed(number, fractionSize) {
    return +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
}

在此处找到:AngularJS filters.js source

答案 8 :(得分:2)

注意:您可能只需要这个 .toFixed() 解决方案来处理非常大的数字

其他发布的解决方案适用于标准数字(低于 1e21)

如果您想处理非常大的数字和非常小的分数,并使用 toFixed 进行正确的四舍五入且不损失准确性,并且无需使用库和自包含函数,一种可能的有效解决方案是使用 BigInt 来避免由于内部 javascript 舍入而导致的准确性损失。

toFixed(number, [digits]) 下面的函数就是这样做的。

只需将大数作为具有所需舍入位数的字符串传递。数字将被正确四舍五入。

这个概念是将数字分成整数部分和小数部分的常用方法,但使用 BigInt() 来保存这两个部分。此后,根据需要对正数和负数进行舍入和处理,而不使用任何 javascript Math 或数字函数,以避免损失准确性。

作为非常特殊的情况下的奖励,其中数字采用非常大的“e”符号,我添加了 eToNumber() 函数,我已在此处发布:https://stackoverflow.com/a/66072001/11606728 将其作为内联进程执行.如果您想维护短代码并且不关心这些数字,则可以将其删除。 [代码中提供了注释以将其删除]。

我已经包含了各种测试用例来测试不同的可能性(其中一些有点奇怪,但确实发生了)。

这个想法可以进一步改进。

希望有用。

/****************************************************************************
* @function    : toFixed(number, [digits])
* @purpose     : Emulate toFixed() for large numbers and
                 large fractional numbers with correct rounding
                 by using the BigInt() built-in Object.
* @version     : 1.01
* @author      : Mohsen Alyafei
* @date        : 03 February 2021
* @param       : {number} [numeric or string] pass large numbers as a string
* @param       : {number} [optional digits]
*              : The number of digits to appear after the decimal point;
*              : this may be a value from 0 and above unlimited.
*              : If this argument is omitted or is negative, it is treated as 0.
*              : Handles large 'e' notation number using the eToNumber() function.digits
*              : See https://stackoverflow.com/a/66072001/11606728
* @returns     : A string representing the given number using fixed-point notation.
****************************************************************************/

function toFixed(num,digits) {
    if (!num && num!==0) return "Cannot read property of null or undefined"; // Can change it to throw Error
    digits<0 && (digits=0);
    digits=digits||0;
    num=eToNumber(num); // Delete this line and function below if larage 'e' notation number are not required
    let wh = (num+="").split((.1).toLocaleString().substr(1,1)), f = wh[1];
    wh = wh[0];
    let fr = (f=f||"0").substr(0,digits), fn = BigInt(fr), w = BigInt(wh), fl = (""+fn).length,
        lZeros = fr.length-fl, minus = wh[0]=="-", inc = (wh<0 || minus) ? BigInt(-1):BigInt(1);
    f[digits]>=5 && (fn+=BigInt(1));
    (fn+="").length > fl && (lZeros-=1);
    lZeros >=0 ? lZeros="0".repeat(lZeros):(fn=fn.substring(1), lZeros="",
               (fn ? w +=inc : ((f[digits]>=5) && (w+=inc))));
    fn = lZeros + fn; L = digits-fn.length;
    L && (fn+="0".repeat(L)); w==0 && minus && (w="-"+w);
    return w+(fn?".":"")+fn;
    }

    //---------------------- Extra Function if needed --------------------------------
    // Delete this function if large 'e' notation number are not required
    // Convert very large 'e' numbers to plain string numbers.
    //--------------------------------------------------------------------------------
    function eToNumber(num) {
        let sign="";
        (num+="").charAt(0)=="-" && (num=num.substring(1),sign ="-");
        let arr = num.split(/[e]/ig); if (arr.length<2) return sign+num;
        let dot=(.1).toLocaleString().substr(1,1), n = arr[0], exp = +arr[1];
        let w = (n=n.replace(/^0+/,'')).replace(dot,''),
          pos = n.split(dot)[1]? n.indexOf(dot)+exp : w.length+exp,
            L = pos-w.length,s=""+BigInt(w);
         w = exp>=0 ? (L>=0 ? s+"0".repeat(L):r()): (pos<=0 ? "0"+dot+"0".repeat(Math.abs(pos))+s:r());
        if (!+w) w=0; return sign+w;
        function r(){return w.replace(new RegExp(`^(.{${pos}})(.)`),`$1${dot}$2`)}}

//================================================
//             Test Cases
//================================================
let r=0; // test tracker
r |= test(35.855,2,"35.86");
r |= test(12.00000015,2,"12.00");
r |= test(35.855,5,"35.85500");
r |= test(35.855,4,"35.8550");
r |= test(1.135,2,"1.14");
r |= test(1.135,3,"1.135");
r |= test(1.135,4,"1.1350");
r |= test(1.135,8,"1.13500000");
r |= test(0.1545,3,"0.155");
r |= test(89.684449,2,"89.68");
r |= test("0.0000001",2,"0.00");
r |= test("0.9993360575508052",3,"0.999");
r |= test("0.999336057550805244545454545",29,"0.99933605755080524454545454500");
r |= test("1.0020739645577939",3,"1.002");
r |= test(0.999,0,"1");
r |= test(0.999,1,"1.0");
r |= test(0.999,2,"1.00");
r |= test(0.975,0,"1");
r |= test(0.975,1,"1.0");
r |= test(0.975,2,"0.98");
r |= test(2.145,2,"2.15");
r |= test(2.135,2,"2.14");
r |= test(2.34,1,"2.3");
r |= test(2.35,1,"2.4");
r |= test("0.0000001",2,"0.00");
r |= test("0.0000001",7,"0.0000001");
r |= test("0.0000001",8,"0.00000010");
r |= test("0.00000015",2,"0.00");
if (r==0) console.log("Tests 01. Standard fractional numbers passed");
//================================================
r=0; // test tracker
r |= test("1234567890123456789444.99",5,"1234567890123456789444.99000");
r |= test("1234567890123456789444.1445",3,"1234567890123456789444.145");
r |= test("1234567890123456789444.14451445144514451745",19,"1234567890123456789444.1445144514451445175");
if (r==0) console.log("Tests 02. Large fractional numbers passed");
//================================================
r=0; // test tracker
r |= test(100,2,"100.00");
r |= test(0,5,"0.00000");
if (r==0) console.log("Tests 03. Non-fractional numbers passed");
//================================================
r=0; // test tracker
r |= test(12345.6789,null,"12346");
r |= test(2.1234,null,"2");
r |= test(12345.6789,undefined,"12346");
r |= test(2.1234,undefined,"2");
r |= test(12345.6789,"","12346");
r |= test(0.1234,"","0");
r |= test(2.1234,"","2");
if (r==0) console.log("Tests 04. Undefined, Null, and Empty Digits passed");
//================================================
r=0; // test tracker
r |= test(1.1155,2,"1.12");
r |= test(1.255,2,"1.26");
r |= test(1.265,2,"1.27");
r |= test(1.275,2,"1.28");
r |= test(1.285,2,"1.29");
r |= test(1.295,2,"1.30");
r |= test(2.05,1,"2.1");
r |= test(2.15,1,"2.2");
r |= test(2.55,1,"2.6");
r |= test(2.65,1,"2.7");
r |= test(2.215,2,"2.22");
r |= test(2.315,2,"2.32");
r |= test(2.715,2,"2.72");
r |= test(2.815,2,"2.82");
r |= test(2.005,2,"2.01");
r |= test(2.105,2,"2.11");
r |= test(2.405,2,"2.41");
r |= test(2.505,2,"2.51");
r |= test(2.605,2,"2.61");
r |= test(2.905,2,"2.91");
r |= test(0.00155,4,"0.0016");
r |= test(2.55,1,"2.6");
r |= test(-2.35,1,"-2.4");
if (r==0) console.log("Tests 05. Correct rounding passed");
//================================================
r=0; // test tracker
r |= test(-1.125,2,"-1.13");
r |= test(-1.15,1,"-1.2");
r |= test(-1.15,1,"-1.2");
r |= test(-1.45,1,"-1.5");
r |= test(-1.65,1,"-1.7");
r |= test(-1.95,1,"-2.0");
r |= test(-2.34,1,"-2.3");
r |= test("-0.024641163062896567",3,"-0.025");
r |= test("-0.024641163062896567",16,"-0.0246411630628966");
r |= test("0.024641163062896567",16, "0.0246411630628966");
r |= test("-0.0246411630628965",16,"-0.0246411630628965");
if (r==0) console.log("Tests 06. Negative numbers rounding passed");
//================================================
r=0; // test tracker
r |= test(.135,2,"0.14");    // without whole part
r |= test(-.135,2,"-0.14");
r |= test("+35.855",2,"35.86");
r |= test("0.0",2,"0.00");
r |= test("-0",2,"-0.00");       //minus 0
r |= test("-0.0",5,"-0.00000");  // minus 0
r |= test("",5,"Cannot read property of null or undefined");        // empty string
r |= test(null,5,"Cannot read property of null or undefined");      //null
r |= test(undefined,5,"Cannot read property of null or undefined"); // undefined
if (r==0) console.log("Tests 07. Special test cases passed");
//================================================
r=0; // test tracker
r |= test(1.1234e1,2,"11.23");      //11.234
r |= test(1.12e2,2,"112.00");       //112
r |= test(-1.1234e2,2,"-112.34");   // -112.34
r |= test(-1.1234e2,4,"-112.3400"); // -112.34
r |= test(-1.1235e2,2,"-112.35");   // -112.35
r |= test(-1.1235e2,1,"-112.4");    // -112.4
if (r==0) console.log("Tests 08. Standard e notation numbers passed");
//================================================

r=0; // test tracker
r |= test("123456789123456789.111122223333444455556666777788889999e+10",16,"1234567891234567891111222233.3344445555666678");
r |= test("1.1235678944556677e2",20,"112.35678944556677000000");
r |= test("99.1235678944556677e2",20,"9912.35678944556677000000");
if (r==0) console.log("Tests 09. Large e notation numbers passed");
//================================================

if (r==0) console.log(`${"-".repeat(22)}\nAll Test Cases Passed.\n${"-".repeat(22)}`);

//================================================
//             Test function
//================================================
function test(n1,n2,should) {
let result = toFixed(n1,n2);
if (result !== should) {console.log(`Output   : ${result}\nShould be: ${should}`);return 1;}
}

答案 9 :(得分:2)

如果您希望数字作为输出,请在其他答案中考虑Math.round()技术。

但是,如果您希望将字符串作为输出,以便向人类提供,那么n.toLocaleString()通常比n.toFixed()更有用。

为什么呢?因为它还会为人类用来阅读的大数字头部添加逗号或句号。例如:

var n = 1859.385

n.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})

// Produces  1,859.39  in USA (locale en-US)
// Produces  1 859,39  in France (locale fr-FR)
// Produces  1.859,39  in Germany (locale de-DE)

规范说当传递undefined作为第一个参数时,将使用用户自己的语言环境(由OS指定)。不幸的是,正如链接文档所示,Mozilla在这种情况下使用了en-US语言环境,但它可能会在将来符合规范。

答案 10 :(得分:1)

我偶然发现了为什么Number.toFixed表现得很奇怪。我看到本机功能不可靠,这是不幸的。出于好奇心看待答案,我发现其中大部分*都没有正确使用数字35.855作为T.J.克劳德慷慨地评论每一个人。

也许这会回答你的问题。

function toFixed(n,precision) {
    var match=RegExp("(\\d+\\.\\d{1,"+precision+"})(\\d)?").exec(n);
    if(match===null||match[2]===undefined) {
        return n.toFixed(precision);
        }
    if(match[2]>=5) {
        return (Number(match[1])+Math.pow(10,-precision)).toFixed(precision);
        }
    return match[1];
    }

正则表达式将您的数字拆分为字符串数组,例如toFixed(35.855,2)["35.855", "35.85", "5"]。如果最后一个数字(精确截止后)为>=5,请将Math.pow(10, -precision)添加到修剪后的数字。如果你以2位小数,.01为3,依此类推,则会增加.002

我不知道这是否万无一失,因为它仍然会对浮点数执行十进制数学运算,这是不可预测的。我可以说它35.85535.86

答案 11 :(得分:1)

这里的喜悦回答应该是最好的答案,而不是那么多的黑客攻击。

   x = 1859.385;
   x = x.toFixed(2);
   alert(x);

给出了错误的四舍五入,即1859.38而不是1859.39

 x = 1859.385;
 x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
 alert(x);

给出正确的舍入1,859.39

唯一的问题是返回的结果是一个包含千位逗号分隔符的字符串,因此不能用于计算。使用正则表达式我从堆栈溢出中删除逗号,最终结果是

 x = 1859.385;
 x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
 x=x.replace(/\,/g,'');
 alert(x);

现在返回1859.39并可用于计算。 正则表达式之前的值,即1,859.39可用于html显示,而未格式化的值1859.39可用于计算。

答案 12 :(得分:1)

我想要简洁,准确,兼具可读性和速度性的东西。阅读完该问题的所有答案以及this particularly helpful answer in a similar question之后,这就是我的解决方案。

const round = (numberToRound, digits = 0, toFixed = false) => {
  const precision = 10 ** digits;
  const n = numberToRound * precision * (1 + Number.EPSILON);
  const roundedNumber = Math.round(n) / precision;
  return toFixed ? roundedNumber.toFixed(digits) : roundedNumber;
};

// rounding by half
console.log(round(0.5));
console.log(round(-0.5));

// fixed decimals
console.log(round(0.5, 2), '( Type:',typeof round(0.5, 2), ')');
console.log(round(0.5, 2, true), '( Type:',typeof round(0.5, 2, true), ')');
console.log(round(-0.5, 2), '( Type:',typeof round(-0.5, 2), ')');
console.log(round(-0.5, 2, true), '( Type:',typeof round(-0.5, 2, true), ')');

// edge cases
console.log(round(1.005, 2) === 1.01);
console.log(round(-1.005, 2) === -1.01);
console.log(round(39.425, 2) === 39.43);
console.log(round(-39.425, 2) === -39.43);
console.log(round(1234.00000254495, 10) === 1234.000002545);
console.log(round(-1234.00000254495, 10) === -1234.0000025449);

// edge cases from other answer's comments.
console.log(round(859.385, 2));
console.log(round(859.3844, 2));
console.log(round(0.000000015, 8))
console.log(round(35.855, 2));

我不喜欢toFixed作为布尔参数,但是它现在可以使用。

答案 13 :(得分:0)

这对我有用 - “hackish”

function customTofix(value, precision) {
    let decimalVal = 0;
    
    if (value !== null) {
        let appendValue = (((value - Math.floor(value)) !== 0) ? (precision <= (value.toString().split(".")[1].length || 0)) ? '1' : '' : '');
        decimalVal = parseFloat(value.toString() + appendValue).toFixed(precision)
    }

    return decimalVal
}

答案 14 :(得分:0)

这是因为JavaScript的浮点表示。

试试这个:

Number.prototype.round = function(digits) {
    digits = Math.floor(digits);
    if (isNaN(digits) || digits === 0) {
        return Math.round(this);
    }
    if (digits < 0 || digits > 16) {
        throw 'RangeError: Number.round() digits argument must be between 0 and 16';
    }
    var multiplicator = Math.pow(10, digits);
    return Math.round(this * multiplicator) / multiplicator;
}

Number.prototype.fixed = function(digits) {
    digits = Math.floor(digits);
    if (isNaN(digits) || digits === 0) {
        return Math.round(this).toString();
    }
    var parts = this.round(digits).toString().split('.');
    var fraction = parts.length === 1 ? '' : parts[1];
    if (digits > fraction.length) {
        fraction += new Array(digits - fraction.length + 1).join('0');
    }
    return parts[0] + '.' + fraction;
}

用法:

var n = 859.385;
console.log(n.round(2)); // 859.39
console.log(n.fixed(2)); // 859.39
console.log(n.round(4)); // 859.385
console.log(n.fixed(4)); // 859.3850

答案 15 :(得分:0)

这是我的解决方案,包括3个功能。

  1. 更正四舍五入。
  2. 仅显示数字。(防止科学计数法)
  3. 删除尾随零。

我将@ user2823670的answerthis组合在一起。

var roundUp = function(num, precision) {
    // Return '' if num is empty string
    if (typeof num === 'string' && !num) return '';

    // Remove exponential notation
    num = toPlainString(num);

    // Fixed round up
    var result = +((+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision));

    // Remove exponential notation (once again)
    result = toPlainString(result);

    return result;
};

var toPlainString = function(num) {
    return ('' + num).replace(/(-?)(\d*)\.?(\d+)e([+-]\d+)/,
        function(a, b, c, d, e) {
            return e < 0
                ? b + '0.' + Array(1 - e - c.length).join(0) + c + d
                : b + c + d + Array(e - d.length + 1).join(0);
        }
    );
}

答案 16 :(得分:0)

function toFixed(num, decimals) {
    return (Math.round((num + Number.EPSILON) * Math.pow(10, decimals)) / Math.pow(10, decimals)).toFixed(decimals)
}

我在这里找到了有效答案-> Round to at most 2 decimal places (only if necessary)

Math.round((num + Number.EPSILON) * 100) / 100

您必须在四舍五入的数字后加上Number.EPSILON

答案 17 :(得分:0)

我从Lam Wei Li

得到了适当的解决方案
function round(number, precision) {
  var shift = function (number, exponent) {
    var numArray = ("" + number).split("e");
    return +(numArray[0] + "e" + (numArray[1] ? (+numArray[1] + exponent) : exponent));
  };
  return shift(Math.round(shift(number, +precision)), -precision);
}

测试结果

round(1.050, 1); // expected 1.1 , result 1.1  (correct)
round(1.005, 2); // expected 1.01, result 1.01 (correct)

round(3456.3456,  3); // 3456.346
round(3456.3456,  2); // 3456.35
round(3456.3456,  1); // 3456.3
round(3456.3456,  0); // 3456
round(3456.3456, -1); // 3460
round(3456.3456, -2); // 3500
round(3456.3456, -3); // 3000

round(undefined, 1        ); // NaN
round(null     , 1        ); // NaN
round("a"      , 1        ); // NaN
round(1        , null     ); // NaN
round(1        , undefined); // NaN
round(1        , "a"      ); // NaN

答案 18 :(得分:0)

toFixed从来没有四舍五入,也不是故意的。

它几乎不能将浮点(指数,尾数)转换为定点(整数,小数)(请参阅definition)。

在执行此操作时,它看起来好像是四舍五入的,因为四舍五入的数字是最接近原始浮点表示的近似值。

可悲的是,toFixed可用于四舍五入已广为流传……嗯,它不能,甚至顾名思义也与此无关。

如果需要取整并加上toFixed填充:

function round(num, precision) {
  var base = 10 ** precision;
  return (Math.round(num * base) / base).toFixed(precision);
}

答案 19 :(得分:0)

toFixed()正常工作! 问题是,859.385在计算机上没有浮点数表示。扫描为最接近的可能值= 859.384999999999991。将此值四舍五入为两位数是859.38,而不是859.39。

这就是原因,许多(特别是对于商业而言很古老的编程语言,例如COBOL)支持BCD数字(二进制​​编码的十进制数),其中每个数字本身被编码为4位(例如不使用AF的十六进制)。 / p>

价格的一般解决方案: -以美分/便士计算并打印NUMBER / 100。

其他解决方案的说明(此处提供的功能): 他们可能会提供一些帮助,但大多数情况下都会失败,例如859.38499999。

答案 20 :(得分:0)

我知道这是一个老问题,但是为什么不做这样的事情:

runOnFunction

答案 21 :(得分:0)

这可能会有所帮助

    tofix2Decimals=function(float){
        if(parseInt(float)==float)return float.toFixed(2);
        $decimals=/\.(\d+)/.exec(float)[1].length;
        $decimals=$decimals>=2?$decimals+1:3;
        float+=Math.pow(10,-$decimals);
        return float.toFixed(2);
    }

答案 22 :(得分:-1)

MDM有一个robust rounding implementation。这里的答案大多数都是准确的。