⚡重温一下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 ÷

完结

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

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

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

相关推荐
everyStudy41 分钟前
前端五种排序
前端·算法·排序算法
甜兒.2 小时前
鸿蒙小技巧
前端·华为·typescript·harmonyos
她似晚风般温柔7894 小时前
Uniapp + Vue3 + Vite +Uview + Pinia 分商家实现购物车功能(最新附源码保姆级)
开发语言·javascript·uni-app
Jiaberrr5 小时前
前端实战:使用JS和Canvas实现运算图形验证码(uniapp、微信小程序同样可用)
前端·javascript·vue.js·微信小程序·uni-app
everyStudy6 小时前
JS中判断字符串中是否包含指定字符
开发语言·前端·javascript
城南云小白6 小时前
web基础+http协议+httpd详细配置
前端·网络协议·http
前端小趴菜、6 小时前
Web Worker 简单使用
前端
web_learning_3216 小时前
信息收集常用指令
前端·搜索引擎
Ylucius6 小时前
动态语言? 静态语言? ------区别何在?java,js,c,c++,python分给是静态or动态语言?
java·c语言·javascript·c++·python·学习
tabzzz6 小时前
Webpack 概念速通:从入门到掌握构建工具的精髓
前端·webpack