⚡重温一下JS精度引发的问题了

前言

最近测试给我提了个BUG,我看到的第一感觉就是这必须是后端的锅

本着不冤枉任何一个好人的态度,我还是自己看了下页面展示、接口回参和逻辑处理部分,最后发现,nnd竟然是我的(JS精度)问题。

想着,应该有些小伙伴挺感兴趣的,索性就把笔记更新到这里吧~~~

正文开始

1,为什么JS会有精度问题

精度问题是因为计算机在存储和计算数字时,使用的是二进制形式。有些十进制数字在转换成二进制时无法精确表示,比如0.1在二进制中是无限循环小数。

因此,当在JavaScript中进行浮点数运算时,就会出现精度误差。

整数和整数相乘,通常不会出现精度问题

1.1,十进制转二进制

乘2取整法(用于小数)

js 复制代码
将0.1转为二进制的过程如下:


0.1 * 2 = 0.2,无整数部分,取0
0.2 * 2 = 0.4,无整数部分,取0
0.4 * 2 = 0.8,无整数部分,取0
0.8 * 2 = 1.6,有整数部分1,取1,剩余小数部分0.6
0.6 * 2 = 1.2,有整数部分1,取1,剩余小数部分0.2
0.2 * 2 = 0.4,无整数部分,取0
... 之后的过程会不断重复

按照这种格式表示,0.1的二进制表示为:**0.0001100110011001...** ,是一个无限循环小数

除2取余法(用于整数)

js 复制代码
将100转为二进制的过程如下:

100 / 2 = 50 余0
50 / 2 = 25 余0
25 / 2 = 12 余1
12 / 2 = 6 余0
6 / 2 = 3 余0
3 / 2 = 1 余1
1 / 2 = 0 余1

然后将所有余数倒序排列,得到数1100100,这就是100的二进制表示。

1.2,二进制转十进制

js 复制代码
将1100100转为十进制的过程如下:

1*2^6 = 64
1*2^5 = 32
0*2^4 = 0
0*2^3 = 0
1*2^2 = 4
0*2^1 = 0
0*2^0 = 0

64+32+0+0+4+0+0=100

1.3,为什么0.1+0.2 !== 0.3 但是 0.2 + 0.2 === 0.4

js 复制代码
0.1(十进制) = 0.0001100110011001(二进制)  超出计算精度,结果保留十六位小数

0.2(十进制) = 0.0011001100110011(二进制)  超出计算精度,结果保留十六位小数

0.3(十进制) = 0.0100110011001100(二进制)  超出计算精度,结果保留十六位小数

0.1+0.2这两个数在二进制表示下都存在精度误差,它们的和不等于精确的0.3,所以0.1+0.2 !== 0.3。

0.2+0.2这两个数在二进制表示下虽然也存在精度误差,但是当它们相加时,这些误差恰好抵消了,使得它们的和等于精确的0.4,所以0.2+0.2 === 0.4。(0.1 + 0.3 === 0.4也同理)

2,JS精度有问题的案例

3,解决方案

3.1,转成整数进行计算

先乘以100化为整数,再除

3.2,转成字符串然后截取

3.3,使用第三方库

Math.js 解决大数计算和精度问题

js 复制代码
math.config({ number: 'BigNumber', precision: 64 }); 

console.log(math.format(math.eval('0.1 + 0.2'))); // '0.3' 

console.log(math.format(math.eval('9007199254740991 + 2'))); // '9.007199254740993e+15'

number-precision 解决浮点数

js 复制代码
NP.plus(0.1, 0.2); // 0.3 + 

NP.minus(1.0, 0.9); // 0.1 - 

NP.times(3, 0.3); // 0.9 * 

NP.divide(0.9, 0.3); // 3 ÷

完结

这篇文章我尽力把我的笔记和想法放到这了,希望对小伙伴有帮助。

欢迎转载,但请注明来源。

最后,希望小伙伴们给我个免费的点赞,祝大家心想事成,平安喜乐。

相关推荐
旧味清欢|5 分钟前
关注分离(Separation of Concerns)在前端开发中的实践演进:从 XMLHttpRequest 到 Fetch API
javascript·http·es6
热爱编程的小曾22 分钟前
sqli-labs靶场 less 8
前端·数据库·less
gongzemin33 分钟前
React 和 Vue3 在事件传递的区别
前端·vue.js·react.js
Apifox1 小时前
如何在 Apifox 中通过 Runner 运行包含云端数据库连接配置的测试场景
前端·后端·ci/cd
-代号95271 小时前
【JavaScript】十四、轮播图
javascript·css·css3
树上有只程序猿1 小时前
后端思维之高并发处理方案
前端
庸俗今天不摸鱼2 小时前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
QTX187302 小时前
JavaScript 中的原型链与继承
开发语言·javascript·原型模式
黄毛火烧雪下2 小时前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox2 小时前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员