通常我们希望0.1+0.2===0.3
为真。但它不是javascript会产生的结果。由于javascript显示十进制浮点数,但内部存储二进制浮点数。所以这会返回false。
如果我们使用chrome开发人员工具控制台,我们会得到以下结果:
0.1+0.2;//0.30000000000000004
0.1+1-1;//0.10000000000000009
0.1 + 0.2 === 0.3 ;// returns false but we expect to be true.
0.1+1-1===0.1;//returns false
由于舍入错误,作为最佳实践,我们不应直接比较非整数。相反,考虑舍入误差的上限。这样的上限称为机器epsilon。
这是epsilon方法:
var eps = Math.pow(2,-53);
function checkEq(x,y){
return Math.abs(x - y) < eps;
}
现在,如果我们检查它会返回true。
checkEq(0.1+0.2,0.3);// returns true
checkEq(0.1+1-1,0.1);//returns true
没关系。但如果我检查一下:
checkEq(0.3+0.6,0.9);// returns false
哪个不合适,而不是我们所期望的。
那么,我们该怎么做才能返回正确的结果?
我试图解决的问题是:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
lxi = x.toString().length - x.toString().indexOf('.') - 1;
lyi = y.toString().length - y.toString().indexOf('.') - 1;
lx = isFloating(x) > -1 ? lxi : 0;
ly = isFloating(y) > -1 ? lyi : 0;
return x.toFixed(lx) - y.toFixed(ly)===0;
}
现在,修好了。如果我像这样检查它会很好:
checkEq(0.3,0.3); //returns true
但是以下内容返回false
checkEq(0.3+0.6,0.9)
首先,它的值存储在binaray浮点数中,然后在计算后返回十进制浮点数。
现在,我如何为checkEq(0.3+0.6,0.9) 0.3.toFixed(lx) and 0.6.toFixed(lx)
中的每个输入设置toFixed()方法,然后只添加:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
x = x.toString().split(/\+ | \- | \/ | \ | \\ */);
y = x.toString().split(/\+ | \- | \/ | \ | \\*/);
for(var i=0;i<x.length,y.length;i++){
//here too I may be wrong...
lxi = x[i].toString().length - x[i].toString().indexOf('.') - 1;
lyi = y[i].toString().length - y[i].toString().indexOf('.') - 1;
// particularly after this would wrong...
lx = isFloating(x[i]) > -1 ? lxi : 0;
ly = isFloating(y[i]) > -1 ? lyi : 0;
//And, here I'm stucked too badly...
//take splitted operators to calculate:
//Ex- '0.3 + 1 - 1'
// Number('0.3').toFixed(1) + Number('1').toFixed(0) - Number('1').toFixed(0)
//But careful, we may not know how many input will be there....
}
//return x.toFixed(lx) - y.toFixed(ly)===0;
}
其他答案也欢迎,但非常感谢帮助我使用我的代码。
答案 0 :(得分:0)
也许您应该尝试一些现有的JS Math库,例如bignumber.js,它支持任意精度算术。从头开始实施所有内容将非常耗时且乏味。
0.3+0.6 //0.8999999999999999
x = new BigNumber('0.3') // "0.3"
y = new BigNumber('0.6') // "0.6"
z = new BigNumber('0.9') // "0.9"
z.equals(x.plus(y)) // true
答案 1 :(得分:0)
我认为你应该为epsilon增加一点价值。
您还可以查看math.js:math.js的比较函数也检查近似相等。比较解释如下:
http://mathjs.org/docs/datatypes/numbers.html#comparison
所以你可以这样做:
math.equal(0.1 + 0.2, 0.3); // true
math.equal(0.3 + 0.6, 0.9); // true
更好的是,math.js支持bignumbers(see docs),所以你可以这样做:
math.equal(math.bignumber(0.1) + math.bignumber(0.2), math.bignumber(0.3);
或使用表达式解析器:
math.config({number: 'bignumber'});
math.eval('0.1 + 0.2'); // returns BigNumber 0.3, not 0.30000000000000004
math.eval('0.1 + 0.2 == 0.3'); // returns true
答案 2 :(得分:0)
不等函数,例如平等(但也有地板和ceil)受到舍入误差的严重影响,并且考虑到epsilon可能在某些情况下有效,但也可能给出错误的答案(例如abs(x-y) < eps
可能会返回是的,而x和y的确切值确实不同);你应该做一个错误分析,以确保它是正常的。没有通用的方法来解决浮点问题:这取决于您的应用程序。如果您的输入是十进制数,并且您只使用加法,减法和乘法,如果精度足够大,则可以使用十进制浮点算法,以便可以准确表示所有数据。您还可以使用合理算术,例如big-rational(未尝试)。