我一直在使用java进行编码,并且最近开始使用javascript编写(准确地说是node.js)。令我发疯的一件事是在十进制数字上添加操作;
考虑以下代码
var a=0.1, b=0.2, c=0.3;
var op1 = (a+b)+c;
var op2 = (b+c)+a;
令我惊讶的是,我发现了op1 != op2
! console.logging op1和op2打印出以下内容:
console.log(op1); 0.6000000000000001
console.log(op2); 0.6
这没有意义。这看起来像是一个bug,因为javascript根本无法忽略算术规则。有人可以解释为什么会发生这种情况吗?
答案 0 :(得分:3)
这是一个浮点错误。
可以用浮点数精确表示的唯一小数可以写为整数分数,分母为2的幂。
例如,0.5可以准确表示,因为它可以写成1/2。 0.3不能。
在这种情况下,变量和表达式中的舍入误差恰好合并在第一种情况下产生错误,但在第二种情况下则不然。
这两种方式都没有在幕后完全表示,但是当您输出该值时,它会将其四舍五入为精度。在一种情况下,它会四舍五入到稍大的数字,而在另一种情况下,它会四舍五入到预期值。
你应该学到的教训是你永远不应该依赖具有精确值的浮点数,特别是在做了一些算术之后。
答案 1 :(得分:0)
这不是一个javascript问题,而是使用浮点数时每种编程语言的标准问题。您的样本编号0.1,0.2和0.3不能表示为有限小数,而是重复十进制,因为它们中包含除数5: 0.1 = 1 /(2 * 5),依此类推。 如果你只使用除数2的小数(如a = 0.5,b = 0.25和c = 0.125),一切都很好。
答案 2 :(得分:0)
这是因为not all floating point numbers can be accurately represented in binary。
将所有数字乘以某个数字(例如,如果处理2个小数点,则为100)。
然后对更大的结果进行算术运算。
算术结束后,除以你在开头乘以的相同因子。
a = 10 * a;
b = 10 * b;
c = 10 * c;
op1 = (a+b)+c;
op2 = (b+c)+a;
op1 = op1 / 10;
op2 = op2 / 10;
答案 3 :(得分:0)
使用浮点数时,您可能需要在比较之前设置数字的精度。
(0.1 + 0.2).toFixed(1) == 0.3
但是,在少数情况下,toFixed在浏览器中的行为方式不同。 这是针对toFixed的修复。
http://bateru.com/news/2012/03/reimplementation-of-number-prototype-tofixed/