Math.round舍入误差

时间:2013-02-27 17:39:42

标签: javascript math rounding

我想将 1.006 四舍五入到两位小数,期望输出为1.01

当我做的时候

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

类似地,

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

所以

  • 每次使用toFixed()是否安全?
  • toFixed()跨浏览器投诉?

请建议我。

P.S:我尝试搜索堆栈溢出以获得类似的答案,但无法得到正确答案。

EDIT:

为什么 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

在哪里

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

3 个答案:

答案 0 :(得分:5)

尝试类似......

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

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

(将任意数字舍入到x小数点)

答案 1 :(得分:1)

我意识到这个问题已经很老了,但是在问到问题后的5年里我仍然遇到这个问题。

我知道这个舍入问题的工作解决方案是将数字转换为字符串,获取所需的精确数,并使用数学规则向上或向下舍入。

Math.round提供意外舍入的示例以及字符串舍入的示例可以在以下小提琴中找到: http://jsfiddle.net/Shinigami84/vwx1yjnr/

function round(number, decimals = 0) {
  let s = '' + number;
  let dot = s.indexOf('.');
  let start = dot + decimals + 1;
  let dec = Number.parseInt(s.substring(start, start + 1));
  let remainder = dec >= 5 ? 1 / Math.pow(10, decimals) : 0;
  let result = Number.parseFloat(s.substring(0, start)) + remainder;
  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在这里不能正常工作,因为0.145乘以100是14.499999999999998,而不是14.5。因此,Math.round会将其向下舍入,就像它是14.4一样。如果将其转换为字符串并减去所需的数字(5),然后使用标准数学规则对其进行舍入,您将得到0.15的预期结果(实际上,0.14 + 0.01 = 0.15000000000000002,使用" toFixed" to得到一个很好的,圆的结果)。

答案 2 :(得分:1)

这个公式Math.round(num*100)/100并不总是很好。例子

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

这是错误的,我们希望它是0.15

说明

问题是我们有这样的浮动对象

0.145 * 100 = 14.499999999999998

第一步

因此,如果我们四舍五入,则需要在product上添加一些内容。

0.145 * 100 + 1e-14 = 14.500000000000009

我假设有时候product可能类似于1.000000000000001,但是如果我们添加它就不会有问题,对吧?

第二步

计算我们应该添加多少?

我们知道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)-只是为了确保我们不会陷入同一取整陷阱。

单线:

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