JS精读丢失

89 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

前言:

成功没有捷径但成长有路径

css必备场景。专注积累,每天记录一个知识点,老概念新理解,重点记录一下

每天梳理一个场景,知识点查漏补缺,充实满足。

正文

背景

刚工作那会遇到的后端返回long类型id,到前端id接收值就发生了变化,那时候知道是精读丢失问题,JavaScript只有Number类型,后来解决方法是规定后端长整型都以String的类型返回。按理说这就算是一个交代了,但是技术人嘛,遇到问题总想多研究一下,为什么会出现这种情况,还有哪些情况下会发生。

// 后端数据
"id": 542236870961287168

// 前端数据
"id": 542236870961287200

分析原因

进制转换,其实跟语言没关系,是存储本身的缺陷,精度丢失并不是语言的问题,而是存储本身固有的缺陷。

问题1,0.1 + 0.2 === 0.30000000000000004 浮点数加减法

浮点数 0.1、0.2不能被精确存储(只能存储科学计数法表示的数)

问题2,大整数的精度丢失

也就是上文提到的那个问题,Number类型有最大最小的安全数范围。JS 中能精准表示的最大整数是 Math.pow(2, 53) 十进制即 9007199254740992,大于这个数就会有舍入操作,导致精度丢失

// number安全整数范围
-9007199254740992 ~ 9007199254740992

更详细的请参考这篇文章:zhuanlan.zhihu.com/p/100353781

解决方法

大体有几种思路

1,工具类库

涉及到金额还是不推荐自己写方法,成熟的工具库能解决很多问题。

有许多支持计算的数学库,比如math.js,decimal.js,D.js等等。

2,长整型要求String

上面讲了number类型是有最大值限制的,在解析的时候,long 类型强制转为 number类型,超出的部分会被舍入。我们一般是要求后端用 string 类型代替 long 类型的。

3,浮点数

3.1 通过乘法,转成整数运算。乘了多少结果再除回来。比如 0.1+0.2 ,转为(0.1 * 10 + 0.2 * 10)/10 = 0.3

3.2 toFixed。浮点数运算的偏差非常小,大多数情况下使用toFixed()对结果进行四舍五入就可以得到正确结果。

但是toFixed并不代表是可靠的,caibaojian.com/js-tofixed.…

总结和收获

作为一个技术人,要有不求甚解的心,遇到问题没关系,重要的是你能从中看到哪些点。