写点什么

JavaScript 小数点计算时失精问题

作者:空城机
  • 2022 年 7 月 20 日
  • 本文字数:821 字

    阅读完需:约 3 分钟

JavaScript小数点计算时失精问题

在页面开发中,不知道各位有没有遇到过 JavaScript 小数点计算失精问题。


我曾经就遇到过0.018 * 100 != 1.8的情况


当时使用的是Vue,界面上要显示百分比,然后使用{{ number * 100 }}。当时就出了小数点精度问题,一连串小数显示在了上面。


查看了一下,number数值是正确的,不是后台接口整活,那么就只有 JavaScript 的小数点精度计算问题了。

解决方法

先来说说解决方法: Math.round((i * 10) * 100) / 100


这种方式通过将需要运算的小数扩大 10 倍 100 倍,将小数扩大到整数后,再进行运算,最后再通过除法缩小到当前倍数


或者对于小数点后一两位的数据也可以通过转换成字符串使用 toFixed 的方式来进行保留小数点位数

原因

产生小数值精度问题的原因是在计算机内部存储数值时,会通过二进制的方式存储,那么当两个数值相加或相乘时,也是通过二级制数字进行计算,然后再将这个二进制结果转换成十进制输出给我们。


同理,小数在计算时也是一样,但是小数转换成二进制会出现问题,像 0.5 这类可以很轻松的转换成二进制,但是其他的数值就非常困难了


例子:在下方例子中,使用toString(2)可以将十进制数值转换成二进制,但是像 0.1,0.2,0.4 这类数值二进制后都是小数点后一系列数字,在0.1 + 0.2时,因为无限循环的数据不可能在计算机内部存在,所以必须要有一个限制,这里对应的 0.1 和 0.2 二进制就不精准了,这样一来,两者相加出来的结果就不可能等于 0.3 了

let n1 = 0.1, n2 = 0.2, n3 = 0.4, n4 = 0.5console.log(n1.toString(2))  // 0.0001100110011001100110011001100110011001100110011001101console.log(n2.toString(2))  // 0.001100110011001100110011001100110011001100110011001101console.log(n3.toString(2))  // 0.01100110011001100110011001100110011001100110011001101console.log(n4.toString(2))  // 0.1console.log(n1 + n2);  // 0.30000000000000004
复制代码


所以可以将 0.1 和 0.2 乘 10 之后相加,除以 10,得到最后的 0.3

console.log((n1 * 10 + n2 * 10) / 10);  // 0.3
复制代码


发布于: 刚刚阅读数: 5
用户头像

空城机

关注

曾经沧海难为水,只是当时已惘然 2021.03.22 加入

业余作者,在线水文 主要干前端的活,业余会学学python 欢迎各位关注,互相学习,互相进步

评论

发布
暂无评论
JavaScript小数点计算时失精问题_JavaScript_空城机_InfoQ写作社区