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

完结

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

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

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

相关推荐
Mr.Liu68 分钟前
小程序30-wxml语法-声明和绑定数据
前端·微信小程序·小程序
7675604799 分钟前
useDateFormat源码解析
前端·源码
Mintopia9 分钟前
Three.js粒子系统开发实战:从基础到性能优化
前端·javascript·three.js
Promise52010 分钟前
大屏"跑马灯" 长列表性能优化
前端·javascript
子玖10 分钟前
初始化项目前的准备
前端·javascript·vue.js
Mintopia10 分钟前
Three.js进阶实战:打造动态光影交互场景 ——结合环境光、聚光灯与相机控制的沉浸式体验
前端·javascript·three.js
贵州数擎科技有限公司11 分钟前
Threejs绘制小兩伞快拿去送给你的女神
前端
Carlos_sam13 分钟前
OpenLayers:封装Overlay的方法
前端·javascript
MariaH13 分钟前
Sequelize模型初探
前端·后端
树豪14 分钟前
跟着官网学 Lynx 之 搭建 Lynx todo-list app
android·前端