我有以下虚拟测试脚本:

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

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

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

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


当前回答

如果需要进行任意精度浮点计算,可以使用我的NPM库gmp-wasm,它基于gmp+MPFR库。您可以轻松设置所需的任何精度,并以固定精度返回结果。

<script src=“https://cdn.jsdelivr.net/npm/gmp-wasm“></script><脚本>gmp.init().then(({getContext})=>{const ctx=getContext({precisionBits:100});常量结果=ctx.Float('0.1').mul(ctx.Flat('0.2'));document.write(`0.1*0.2=`+result.toFixed(2));ctx.destroy();});</script>

其他回答

不优雅,但能完成任务(删除尾随零)

var num = 0.1*0.2;
alert(parseFloat(num.toFixed(10))); // shows 0.02

我喜欢佩德罗·拉达里亚的解决方案,并使用类似的方法。

function strip(number) {
    return (parseFloat(number).toPrecision(12));
}

与Pedros解决方案不同,这将向上取整0.999……重复,并精确到最低有效位数的正负一。

注意:当处理32位或64位浮点时,应该使用toPrecision(7)和toPrecision(15)以获得最佳结果。有关原因的信息,请参阅此问题。

你是对的,原因是浮点数的精度有限。将有理数存储为两个整数的除法,在大多数情况下,您可以存储数字而不损失任何精度。在打印时,您可能希望将结果显示为分数。有了我提出的表示法,它就变得微不足道了。

当然,这对非理性数字没有太大帮助。但您可能希望优化您的计算,使其产生的问题最少(例如,检测sqrt(3)^2等情况)。

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;以有效数字表示的精度;始终应用精度;随机数。

链接到详细比较

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

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