JS 遵循IEEE 754规范,采用双精度存储(double precision),占用 64 bit。
精度缺失:
精度缺失最典型例子:
0.1+0.2 != 0.3(true);0.1+0.2 = 0.30000000000000004
造成原因,浮点数的表示:
浮点数:0.1 >> 0.0001 1001 1001 1001…(1001无限循环)0.2 >> 0.0011 0011 0011 0011…(0011无限循环)
0.1,0.2的二进制表示的是一个无限循环小数,目前 JS 采用的是浮点数标准需要对这种无限循环的二进制进行截取,从而导致了精度丢失,造成了0.1不再是0.1,截取之后0.1变成了 0.100…001,0.2变成了0.200…002,所以两者相加的数大于0.3。
这个网站统计了不同语言计算0.1+0.2的结果:http://0.30000000000000004.com/ (可以作为学习了解一下)
解决方案:第三方库有math.js、decimal.js等。手写方案通常通过转化整数进行计算后还原。
最大安全整数:
JS 的最大和最小安全整数值:
最大值:Number.MAX_SAFE_INTEGER // 9007199254740991 ;最小值:Number.MIN_SAFE_INTEGER) //-9007199254740991
当超出这个值范围之后,数字值将不再准确。
典型案例:在后端发送给前端数据的时候,前端通过Json.parse()进行数据处理的时候,数据值不在范围内就会出现数据错误的问题。
造成原因:也是由于双精度浮点数导致最大数为2^53 - 1
解决方案:第三方库有bignum、bigint等。手写方案推荐该类字段做字符串处理。
总结:
从上面两个例子看出,问题的根源其实是关于IEEE 754规范的,这个问题并不只是在Javascript中才会出现,任何使用二进制浮点数的编程语言都会有这个问题。
要理解出的问题和自拟方案的伙伴可以去查一查了解下IEEE 754标准规范,才能从本质上去看透很多东西。只是单纯寻找解决方案不妨试试推荐的第三方库吧。