我有以下虚拟测试脚本:

函数测试(){变量x=0.1*0.2;document.write(x);}测试();

这将打印结果0.020000000000000004,而它应该只打印0.02(如果您使用计算器)。据我所知,这是由于浮点乘法精度的错误。

有没有人有一个好的解决方案,在这种情况下,我得到了正确的结果0.02?我知道还有一些函数,比如toFixed或舍入,这是另一种可能,但我真的希望在不进行任何切割和舍入的情况下打印整个数字。我只是想知道你们中的一个人是否有一些好的、优雅的解决方案。

当然,否则我会舍入到10位数左右。


当前回答

phpjs.org中的round()函数工作得很好:http://phpjs.org/functions/round

num = .01 + .06;  // yields 0.0699999999999
rnum = round(num,12); // yields 0.07

其他回答

var times = function (a, b) {
    return Math.round((a * b) * 100)/100;
};

---或---

var fpFix = function (n) {
    return Math.round(n * 100)/100;
};

fpFix(0.1*0.2); // -> 0.02

---此外---

var fpArithmetic = function (op, x, y) {
    var n = {
            '*': x * y,
            '-': x - y,
            '+': x + y,
            '/': x / y
        }[op];        

    return Math.round(n * 100)/100;
};

---如中所示---

fpArithmetic('*', 0.1, 0.2);
// 0.02

fpArithmetic('+', 0.1, 0.2);
// 0.3

fpArithmetic('-', 0.1, 0.2);
// -0.1

fpArithmetic('/', 0.2, 0.1);
// 2

我有一个变通办法。例如,仅与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);
    }       
}

可怕但有效:)

您得到的结果是正确的,并且在不同语言、处理器和操作系统中的浮点实现之间相当一致——唯一改变的是当浮点实际上是双倍(或更高)时的不准确程度。

二进制浮点中的0.1与十进制中的1/3相似(即永远为0.333333333333333…),只是没有准确的方法来处理它。

如果您处理的是浮点数,那么总是会出现小的舍入误差,因此您也必须将显示的结果舍入到合理的值。作为回报,您可以得到非常快速和强大的算法,因为所有计算都是在处理器的本地二进制中进行的。

大多数情况下,解决方案不是切换到定点运算,主要是因为它速度慢得多,99%的时间你不需要精度。如果你处理的东西确实需要这样的准确性(例如金融交易),那么无论如何,Javascript可能不是最好的工具(因为你想要强制执行定点类型,静态语言可能更好)。

您正在寻找一个优雅的解决方案,但恐怕就是这样:浮点运算速度很快,但舍入误差很小-在显示结果时总是舍入到合理的值。

decimal.js、big.js或bignumber.js可用于避免Javascript中的浮点操作问题:

0.1 * 0.2                                // 0.020000000000000004
x = new Decimal(0.1)
y = x.times(0.2)                          // '0.2'
x.times(0.2).equals(0.2)                  // true

big.js:极简主义;易于使用;以小数位数表示的精度;精度仅适用于除法。

bignumber.js:基数2-64;配置选项;NaN;无穷以小数位数表示的精度;精度仅适用于除法;基本前缀。

decimal.js:基数2-64;配置选项;NaN;无穷非整数幂,exp,ln,log;以有效数字表示的精度;始终应用精度;随机数。

链接到详细比较

避免在使用整数的操作过程中处理浮点

正如迄今为止投票最多的答案所述,你可以使用整数,这意味着你所使用的每一个小数乘以10,然后将结果除以所使用的相同数字。

例如,如果使用2个小数,则在执行运算之前,将所有因子乘以100,然后将结果除以100。

下面是一个示例,Result1是通常的结果,Result2使用解决方案:

var Factor1=“1110.7”;var Factor2=“2220.2”;var Result1=数字(因子1)+数字(因子2);var Result2=((数量(因子1)*100)+(数量(系数2)*100))/100;var Result3=(Number(parseFloat(Number(Factor1))+parseFlat(Number(Factor2))).toPecision(2));document.write(“Result1:”+Result1+“<br>Result2:”+Result2+“<br>Result3:”+Result3);

第三个结果是显示改用parseFloat时发生的情况,这在我们的案例中产生了冲突。