简体   繁体   English

Math.round 舍入误差

[英]Math.round Rounding Error

I Want to round 1.006 to two decimals expecting 1.01 as output我想将1.006舍入到两位小数,期望 1.01 作为输出

When i did当我做

var num = 1.006;
alert(Math.round(num,2)); //Outputs 1 
alert(num.toFixed(2)); //Output 1.01

Similarly,相似地,

var num =1.106;
alert(Math.round(num,2)); //Outputs 1
alert(num.toFixed(2));; //Outputs 1.11

So所以

  • Is it safe to use toFixed() every time ?每次都使用 toFixed() 安全吗?
  • Is toFixed() cross browser complaint? toFixed() 是否跨浏览器投诉?

Please suggest me.请建议我。

PS: I tried searching stack overflow for similar answers, but could not get proper answer. PS:我尝试在堆栈溢出中搜索类似的答案,但没有得到正确的答案。

EDIT:

Why does 1.015 return 1.01 where as 1.045 returns 1.05为什么1.015返回 1.01 而1.045返回 1.05

var num =1.015;
alert(num.toFixed(2)); //Outputs 1.01
alert(Math.round(num*100)/100); //Outputs 1.01

Where as然而

var num = 1.045;
alert(num.toFixed(2)); //Outputs 1.04
alert(Math.round(num*100)/100); //Outputs 1.05

Try something like...尝试类似...

Math.round(num*100)/100


1) Multiple the original number by 10^x (10 to the power of x)
2) Apply Math.round() to the result
3) Divide result by 10^x

from: http://www.javascriptkit.com/javatutors/round.shtml来自: http : //www.javascriptkit.com/javatutors/round.shtml

(to round any number to x decimal points) (将任何数字四舍五入到 x 个小数点)

This formula Math.round(num*100)/100 is not always good.这个公式Math.round(num*100)/100并不总是好的。 Example例子

Math.round(0.145*100)/100 = 0.14

this is wrong, we want it to be 0.15这是错误的,我们希望它是0.15

Explanation解释

The problem is that we have floats like that问题是我们有这样的浮动

0.145 * 100 = 14.499999999999998

step one第一步

so If we round, we need to add a little bit to our product .所以如果我们圆,我们需要在我们的product添加一点。

0.145 * 100 + 1e-14 = 14.500000000000009 0.145 * 100 + 1e-14 = 14.500000000000009

I assume that sometimes the product might be something like 1.000000000000001 , but it would not be a problem if we add to it, right?我认为有时product可能类似于1.000000000000001 ,但如果我们添加它就不会有问题,对吧?

step two第二步

Calculate how much should we add?计算我们应该添加多少?

We know float in java script is 17 digits.我们知道 java 脚本中的 float 是 17 位数字。

let num = 0.145
let a = Math.round(num*100)/100
let b = a.toString().length
let c = 17-b-2
let result = Math.round(num*100 + 0.1**c)/100
console.log(result)
console.log('not - ' + a )

(-2) - is just to be sure we are not falling into the same trap of rounding. (-2) - 只是为了确保我们不会陷入同样的​​舍入陷阱。

One-liner:单线:

let num = 0.145
let result = Math.round(num*100 + 0.1**(17-2-(Math.round(num*100)/100).toString().length))/100

Extras附加功能

Remember, that everything above is true for positive numbers.请记住,以上所有内容对于正数都是正确的。 If you rounding negative number you would need to subtract a little bit.如果您舍入负数,则需要减去一点。 So the very final One-liner would be:所以最后的 One-liner 将是:

let num = -0.145
let result = Math.round(num*100 + Math.sign(num)*0.1**(17-2-(Math.round(num*100)/100).toString().length))/100

I realize this problem is rather old, but I keep running into it even 5 years after the question has been asked.我意识到这个问题已经很老了,但是在提出这个问题 5 年后,我仍然遇到它。

A working solution to this rounding problem I know of is to convert the number to a string, get the required precision number and round up or down using math rules.我知道的这个舍入问题的有效解决方案是将数字转换为字符串,获得所需的精度数字并使用数学规则向上或向下舍入。

An example where Math.round provides unexpected rounding and an example of string rounding can be found in the following fiddle: http://jsfiddle.net/Shinigami84/vwx1yjnr/ Math.round 提供意外舍入的示例和字符串舍入的示例可以在以下小提琴中找到: http : //jsfiddle.net/Shinigami84/vwx1yjnr/

function round(number, decimals = 0) {
    let strNum = '' + number;
    let negCoef = number < 0 ? -1 : 1;
    let dotIndex = strNum.indexOf('.');
    let start = dotIndex + decimals + 1;
    let dec = Number.parseInt(strNum.substring(start, start + 1));
    let remainder = dec >= 5 ? 1 / Math.pow(10, decimals) : 0;
    let result = Number.parseFloat(strNum.substring(0, start)) + remainder * negCoef;
    return result.toFixed(decimals);
}
let num = 0.145;
let precision = 2;

console.log('math round', Math.round(num*Math.pow(10, precision))/Math.pow(10, precision));
// 0.145 rounded down to 0.14 - unexpected result
console.log('string round', round(num, precision));
// 0.145 rounded up to 0.15 - expected result

Math.round doesn't work properly here because 0.145 multiplied by 100 is 14.499999999999998, not 14.5. Math.round 在这里不能正常工作,因为 0.145 乘以 100 是 14.499999999999998,而不是 14.5。 Thus, Math.round will round it down as if it was 14.4.因此,Math.round 会将其四舍五入,就好像它是 14.4。 If you convert it to a string and subtract required digit (5), then round it using standard math rules, you will get an expected result of 0.15 (actually, 0.14 + 0.01 = 0.15000000000000002, use "toFixed" to get a nice, round result).如果您将其转换为字符串并减去所需的数字 (5),然后使用标准数学规则对其进行四舍五入,您将获得 0.15 的预期结果(实际上,0.14 + 0.01 = 0.15000000000000002,使用“toFixed”获得一个漂亮的圆形结果)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM