js中数字精度丢失问题
文章类型:Javascript
发布者:hp
发布时间:2023-03-03
在js计算中,有时候结果值并不是按我们想想那么出现,比如0.1+0.2并不等于0.3
一:原因
浮点数是一种数据标准,整数也可用浮点数的格式来存储,js主流Nuber采用IEEE754规范中64位双精度浮点运算编码,主要的优点是可以处理整数、小数,节省存储空间
计算机存储二进制即为:符号位+指数位+小数部分 (阶数),JS 中能精准表示的最大整数是 Math.pow(2, 53) 十进制即 9007199254740992
浮点数:
单精度浮点数(float):在内存中占4个字节、有效数字8位、表示范围:-3.40E+38 ~ +3.40E+38
1位符号位+8位指数位+23位小数部分
双精度浮点数(double):在内存中占8个字节、有效数字16位、表示范围:-1.79E+308 ~ +1.79E+308
1位符号位+11位指数位+52位小数部分
形式:
1:十进制数形式
2:科学计数法形式
在js运算中,都是转成二进制后进行计算,最多存储64位二进制数,
0.1 + 0.2 === 0.3 // false
// 0.1 和 0.2 都转化成二进制后再进行运算
0.00011001100110011001100110011001100110011001100110011010 +
0.0011001100110011001100110011001100110011001100110011010 =
0.0100110011001100110011001100110011001100110011001100111
// 转成十进制正好是 0.30000000000000004
存储双精度浮点数先把十进制转化为二进制科学计数形式,然后以自己的规则(符号位+(指数位+指数偏移量的二进制)+小数部分)进行存储
因为存储有位数限制,并且某些十进制浮点数转二进制会出现循环,会造成二进制的舍入操作(0->1),当再转换回去就出现了误差
二:解决方案
1:用三方库 Math.js、big.js、bignumber.js
2:针对大数的整数可以考虑使用 bigint 类型
3:小数乘以倍数变成整数计算,再除以倍数变成原来的数
4:保留位数少,可以截取部分,比如toFixed、toPrecision等