前端中Javascript精度问题理解

1.Javascript 精度问题的产生

精度问题其实是一个"共性"问题
日常生活中的"十进制"

  1. 精度问题的产生:使用"十进制除法"无法除尽的时候就会产生精度问题,例如1/3无法在十进制中除尽。
  2. 精度问题的描述:那我们表达这种无法除尽的问题是用0.3(3循环)来描述。

计算机中的"二级制"

  1. 精度问题的产生:二进制中在无法乘尽的时候会产生精度问题。

  2. 精度问题的描述 :计算机由于存储空间限制,无法像十进制那样使用循环表示,因此只能有限的描述数字精度,目前描述方式主要采用四种"浮点型":单精度32位,延伸单精度43位、双精度64位、延伸双精度90位。尽管储存位数很多,但毕竟是有限的。这种 "有限性 " 就导致了java、c++、javascript等计算机语言中的"精度丢失"。

二进制转化:

二进制整数:除法。"二进制"很少存在无法除尽的时候,因为除以二余数要不是0、1,而我们需要的就是0、1。

二进制小数:乘法。经常存在无法乘进的时候,因为小数位乘以2后,数值截整,剩下小数继续乘以2。0

2.Javascript中的精度存储原因

js采用的是浮点运算标准,而IEEE规定的浮点数值运算标准主要有四种方式来保证精度:单精度(32位)、延伸单精度(43位)、双精度(64位)、延伸双精度(80位)。其中js采用的是双精度64位,其中小数部分最多支持53位的存储,如果超出会被截断。

3.工作中哪些场景可能会遇到js精度问题

场景1小数循环引起的精度问题 :(小数运算)

case1:比如我们在控制台输入:1.15 * 100 ,那么展示的不是115而是114.999999999999。如果我们向下取整Math.floor,再除以100的话,那么值就变成了1.14,少了0.01。在下付款单的时候,我们经常会遇到这样会那样的乘法除法运算,很可能因为类似情况出现精度丢失问题。

case2:

js 复制代码
0.1 + 0.2 != 0.3 // True
因为先把0.1、0.2的二进制分别算出来,结果不等于0.3的二进制表示。

场景2大数过大引起的精度问题 - 前后端大数据值id传递:前端获取到的roomid10976458979374928, 后端返回的:roomid10976458979374929。并且前端在network中看到的都是10976458979374928

这个时候需要先判断是不是缓存的问题,排除缓存问题后,可以考虑是否为精度问题。

那为什么java中可以正常存储呢?因为js中Number类型的数字范围是:-2^53 + 1 到 2^53 - 1,而java中的取值范围是-2^63 + 1 到 2^63 - 1,比js要大很多,所以在java中没有出现这个问题。

场景3:toFixed(n)API截取小数位不准确。 问题原因:toFix不是按照银行家的四舍五入规则进行截取的, 而是有自己的一套四舍六入五考虑(五后任有数就进一,五后无数字看前面,五前为奇数应舍去,五前为偶要进一),那么当我们截取两位的时候,并且第二位小数小于5,第三位小数大于5,那么就会导致不会向前进一位。此外返回的类型是字符串类型也需要额外转换。

js 复制代码
0.615.toFixed(2) // 返回字符串'0.61'而不是'0.62'
1.35.toFixed(1) // '1.4' 正确
1.335.toFixed(2) // '1.33'  错误
1.3335.toFixed(3) // '1.333' 错误
1.33335.toFixed(4) // '1.3334' 正确
1.333335.toFixed(5)  // '1.33333' 错误
1.3333335.toFixed(6) // '1.333333' 错误

怎么判断一个Number类型数字是否在允许的精度范围内呢?

在js中Number类型的数字范围是:-2^53 + 1 到 2^53 - 1 ES6中引入了Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER这两个常量来表示上下限范围。 Number.isSafeInteger()用来判断一个整数是否落在这个范围之内。

4.怎么解决或者避免js精度问题

场景1:小数前端运算导致的精度丢失

场景2:小数位截取toFixed(2)-API导致的精度丢失

场景3:大数前端运算导致的精度丢失

场景4:后端id传大数,前端回显精度丢失

如果是存储位置不够导致的,可以通过第三方库decimal.js使用

相关推荐
前端郭德纲6 分钟前
深入浅出ES6 Promise
前端·javascript·es6
就爱敲代码12 分钟前
ES6 运算符的扩展
前端·ecmascript·es6
王哲晓33 分钟前
第六章 Vue计算属性之computed
前端·javascript·vue.js
究极无敌暴龙战神X39 分钟前
CSS复习2
前端·javascript·css
风清扬_jd1 小时前
Chromium HTML5 新的 Input 类型week对应c++
前端·c++·html5
Ellie陈1 小时前
Java已死,大模型才是未来?
java·开发语言·前端·后端·python
想做白天梦2 小时前
双向链表(数据结构与算法)
java·前端·算法
有梦想的咕噜2 小时前
Electron 是一个用于构建跨平台桌面应用程序的开源框架
前端·javascript·electron
yqcoder2 小时前
electron 监听窗口高端变化
前端·javascript·vue.js
Python私教2 小时前
Flutter主题最佳实践
前端·javascript·flutter