我有以下虚拟测试脚本:
函数测试(){变量x=0.1*0.2;document.write(x);}测试();
这将打印结果0.020000000000000004,而它应该只打印0.02(如果您使用计算器)。据我所知,这是由于浮点乘法精度的错误。
有没有人有一个好的解决方案,在这种情况下,我得到了正确的结果0.02?我知道还有一些函数,比如toFixed或舍入,这是另一种可能,但我真的希望在不进行任何切割和舍入的情况下打印整个数字。我只是想知道你们中的一个人是否有一些好的、优雅的解决方案。
当然,否则我会舍入到10位数左右。
您得到的结果是正确的,并且在不同语言、处理器和操作系统中的浮点实现之间相当一致——唯一改变的是当浮点实际上是双倍(或更高)时的不准确程度。
二进制浮点中的0.1与十进制中的1/3相似(即永远为0.333333333333333…),只是没有准确的方法来处理它。
如果您处理的是浮点数,那么总是会出现小的舍入误差,因此您也必须将显示的结果舍入到合理的值。作为回报,您可以得到非常快速和强大的算法,因为所有计算都是在处理器的本地二进制中进行的。
大多数情况下,解决方案不是切换到定点运算,主要是因为它速度慢得多,99%的时间你不需要精度。如果你处理的东西确实需要这样的准确性(例如金融交易),那么无论如何,Javascript可能不是最好的工具(因为你想要强制执行定点类型,静态语言可能更好)。
您正在寻找一个优雅的解决方案,但恐怕就是这样:浮点运算速度很快,但舍入误差很小-在显示结果时总是舍入到合理的值。
我有一个变通办法。例如,仅与10E^x相乘不适用于1.1。
function sum(a,b){
var tabA = (a + "").split(".");
var tabB = (b + "").split(".");
decA = tabA.length>1?tabA[1].length:0;
decB = tabB.length>1?tabB[1].length:0;
a = (tabA[0]+tabA[1])*1.0;
b = (tabB[0]+tabB[1])*1.0;
var diff = decA-decB;
if(diff >0){
//a has more decimals than b
b=b*Math.pow(10,diff);
return (a+b)/Math.pow(10,decA);
}else if (diff<0){
//a has more decimals than b
a=a*Math.pow(10,-diff);
return (a+b)/Math.pow(10,decB);
}else{
return (a+b)/Math.pow(10,decA);
}
}
可怕但有效:)