Javascript toFixed 不四舍五入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10015027/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 23:30:20  来源:igfitidea点击:

Javascript toFixed Not Rounding

javascript

提问by user1172854

I'm using javascript to bind to some checkboxes, and the toFixed(2)is not rounding up. Any ideas why it's not rounding? For instance, if the number is 859.385it's only displaying 859.38instead of 859.39.

我正在使用 javascript 绑定到一些复选框,并且toFixed(2)没有四舍五入。任何想法为什么它不四舍五入?例如,如果数字是859.385它只显示859.38而不是859.39

I've also read that the toFixedcan round differently depending on which browser you are using, anyone know of a way around this so that my javascript calculations match my php calculations?

我还读到,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));

回答by user2823670

I have yet to find a number that toFixed10 does wrong. Can anybody else?

我还没有找到一个 toFixed10 做错的数字。其他人可以吗?

Thanks to blgand his answerwhich pointed me to Mozilla's toFixed10()method.

感谢blg他的回答,让我看到了 Mozilla 的toFixed10()方法。

Using that I came up with this short one liner, which indeed covers all cases mentioned here...

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

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

回答by Shura

I made this to use in all financial data as a best rounding function. You can test it on all problematic numbers. Javascript allows some sort of precision, so I used it to make almost every number be rounded as expected.

我将此作为最佳舍入函数用于所有财务数据。您可以在所有有问题的数字上对其进行测试。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;
    }

回答by jfriend00

In Chrome, toFixed()rounds:

在 Chrome 中,toFixed()四舍五入:

859.385 ==> 859.38
859.386 ==> 859.39

When I look at the ECMAScript 5th edition specification for .toFixed()(section 15.7.4.5), I do not see it explicitly describe rounding though it does describe something fairly obtusely that may be what Chrome has implemented.

当我查看ECMAScript 第 5 版规范.toFixed()(第 15.7.4.5 节)时,我没有看到它明确描述舍入,尽管它确实描述了一些相当迟钝的东西,这可能是 Chrome 已经实现的。

It appears to me that if you want to control it with explicit rounding, then you should probably use the oft-suggested workaround of:

在我看来,如果您想通过显式舍入来控制它,那么您可能应该使用经常建议的解决方法:

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

This will guarantee that you get predictable rounding like you are used to.

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

Working demo here: http://jsfiddle.net/jfriend00/kvpgE/

这里的工作演示:http: //jsfiddle.net/jfriend00/kvpgE/

回答by InsOp

Since in javascripts' toFixed-function, the floating point number5does not belong to the upper half of an integer, the given number is rounded down if you have numbers like these:

由于在 javascripts 的 toFixed 函数中,浮点数5不属于整数的上半部分,因此如果您有以下数字,则给定的数字会四舍五入:

859.385.toFixed(2) // results in 859.38

859.385.toFixed(2) // results in 859.38

for a matter of fact you might append trailing floating point numbers (except zero) like here:

事实上,您可能会像这样附加尾随浮点数(零除外):

859.3851.toFixed(2) // results in 859.39

859.3851.toFixed(2) // results in 859.39

Therefore developers tend to add numbers like 0.00000000001in order for it to be rounded appropriate and to not accidentally change the value of the number.

因此,开发人员倾向于添加数字0.00000000001,以便对其进行适当的四舍五入,并且不会意外更改数字的值。

So I came up with a function which adds such a number depending on how many digits you want your floating point number to be fixed:

所以我想出了一个函数,它根据您希望固定浮点数的位数来添加这样的数字:

    // 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

回答by theycallmethesloth

Another good number to try along with 35.855 is 1.005

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

I don't think Robert Messerle's solution handles 1.005

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

The rounding decimal example here https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round$revision/1383484#Decimal_rounding converts numbers to exponential notation and seems to get better results.

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

I created a fiddle here http://jsfiddle.net/cCX5y/2/that demos the native, Robert Messerle example above (called toFixedB) and the one from Mozilla docs (called toFixed10).

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

I have yet to find a number that toFixed10 does wrong. Can anybody else?

我还没有找到一个 toFixed10 做错的数字。其他人可以吗?

回答by kennebec

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)

/* returned value: (Number) 35.86 */

/* 返回值:(数字)35.86 */

回答by Wiimm

toFixed()works correctly! The problem is, that 859.385 has no representation as float at a computer. It is scanned as nearest possible value = 859.384999999999991. And rounding this value to 2 digits is 859.38 and not 859.39.

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

This is the reasons, that many programming languages (especially old for commerce, e.g. COBOL) support BCD numbers (binary coded decimals), where each digit is coded by itself into 4 bits (like hex without using A-F).

这就是许多编程语言(尤其是旧的商业语言,例如 COBOL)支持 BCD 数(二进制编码的十进制数)的原因,其中每个数字都被自己编码为 4 位(如十六进制而不使用 AF)。

A general solution for prices: Calculate in cent/penny and print NUMBER/100.

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

A note to other solutions (functions provided here): They may help for some numbers, but mostly fail for e.g. 859.38499999.

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

回答by jasonlfunk

You can use the Math.round()to round the number. If you want to round to a specific decimal point you can employ a little math:

您可以使用Math.round()来舍入数字。如果你想四舍五入到一个特定的小数点,你可以使用一点数学:

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

回答by jasonlfunk

I stumbled upon this wondering why Number.toFixedwas behaving strangely. I see that the native function is unreliable, which is unfortunate. Looking over the answers out of curiosity, I see most* of them don't behave properly with the number 35.855as T.J. Crowder graciously commented on every one.

我偶然发现了这一点,想知道为什么Number.toFixed行为异常。我看到本机功能不可靠,这是不幸的。出于好奇查看答案,我发现其中大多数*在数字上表现得不正确,35.855因为 TJ Crowder 对每个答案都彬彬有礼地发表了评论。

Maybe this will answer your question.

也许这会回答你的问题。

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];
    }

The regex splits your number into an array of strings such as in toFixed(35.855,2): ["35.855", "35.85", "5"]. If the last number (after the precision cutoff) is >=5, add Math.pow(10, -precision)to the trimmed number. This will add .01if you're cutting off at 2 decimals, .002at 3, so on and so forth.

正则表达式将您的数字拆分为一个字符串数组,例如 in toFixed(35.855,2): ["35.855", "35.85", "5"]。如果最后一个数字(在精度截止之后)是>=5,则添加Math.pow(10, -precision)到修剪后的数字。.01如果您在小数点后 2 位、.0023 位等处截断,这将相加。

I don't know if this is foolproof, since it still performs decimal math on floats which can be unpredictable. I can say it rounds 35.855up to 35.86.

我不知道这是否万无一失,因为它仍然对可能无法预测的浮点数执行十进制数学。我可以说它四舍五入35.85535.86.

回答by Bodin

I ran into this same problem today, and even trying suggestions in other answers I found that I still did not receive the result I expected. Finally, as I'm using AngularJS for my current project when running into this, I figured I check if AngularJS has already solved the same kind of problem before and indeed they had. Here's the solution they use and it works perfectly for me:

我今天遇到了同样的问题,即使尝试了其他答案中的建议,我发现我仍然没有收到我预期的结果。最后,当我遇到这个问题时,我正在将 AngularJS 用于我当前的项目,我想我会检查 AngularJS 之前是否已经解决了同样的问题,并且确实已经解决了。这是他们使用的解决方案,它非常适合我:

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

Found here: AngularJS filters.js source

在这里找到:AngularJS filters.js 源代码