关于JavaScript数字精度问题

几年开发经验都会有小数计算和数字字符串转为数字的场景,这两个场景总会遇到精度丢失的问题,下面就根据这两个场景分析一下原因,并给出解决方案。

关于小数计算问题

下面是一个测试例子

var num = 0.1 + 0.2
console.log(num) // 0.30000000000000004

为什么会出现 0.1 + 0.2 = 0.30000000000000004?这个是什么原因造成的呢?怎么解决 0.1 + 0.2 ! = 0.3?下面是我总结的,如果有不对的地方还请各位留言。

原因
  • 0.1和0.2这两个都是浮点数
  • 在js底层浮点数相加都是采用二进制来表示
  • 0.1转为二进制是一个无限小数,所以在内存中取出来进行计算就造成了精度丢失
  • 由此就可以知道0.1+0.2!=0.3
    但是这样还有一个问题,看下面示例
var num = 0.1
console.log(num) // 0.1

如果按照上面说的那这个都是浮点数转为二进制那肯定是无限小数,这console的结果怎么是0.1呢?
这个是我看了一些文档摘录

既然知道了原因,下面是我处理的方法

废话不多说,这个是我用的最简单的方法

var num = (0.1 * 10 + 0.2 * 10) / 10
console.log(num) // 0.3

我之所以采用这个方案的原因是浮点数计算采用二进制在进制转换的时候精度丢失,那我们反其道而行之,我们可以使用整数相加,先把所有的浮点数转为整数,最后在对整数除10,这样就可以解决了。

关于数字字符串转为number

下面有一个例子

var str = '12345678987654321'
console.log(Number(str) + 1) // 12345678987654320

var str = '123456789876543212'
console.log(Number(str) + 1) // 123456789876543220

var str = '1234567898765432123'
console.log(Number(str) + 1) // 1234567898765432000

我们都知道字符串数字可以进行算术运算,但是为什么这个值不对呢?其实之所以有这个原因是因为number转数字有最大范围和最小范围,它的范围是±1.7976931348623157e+308,如果超过这个范围number转换的时候会造成精度丢失,其实大概应该是±9007199254740992,也就是如果字符串的长度超过16位有可能就超过精度了。

js内置方法BigInt进行算术运算
var str = '12345678987654321'
console.log(BigInt(str) + BigInt(1)) // 12345678987654322n

var str = '123456789876543212'
console.log(BigInt(str) +  BigInt(1)) // 123456789876543213n

var str = '1234567898765432123'
console.log(BigInt(str) +  BigInt(1)) // 1234567898765432124n

注意BigInt的数据不能直接和number进行算术运算不然报错
从上面的代码我们可以看到这个时候虽然在数字后面多了一个n,我们可以采用下面方法过滤n

String(BigInt(str)).split('n')[0]

虽然这样做进行数字计算,但是还是无法满足这个字符串转为number,这个最后还是一个字符串,如果是后台对数据兼容还可以,但是要是后台接受必须是数字,那这个还是不满足,那我们就需要第三方插件了,比如BigNumber、decimal等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值