浏览器处理数字运算时精度丢失的方法

  • 为什么0.1 + 0.2 不等于0.3。因为计算机不能精确表示0.1, 0.2这样的浮点数,计算时使用的是带有舍入误差的数

  • 并不是所有的浮点数在计算机内部都存在舍入误差,比如0.5就没有舍入误差

1.出现的原因

计算机的二进制实现和位数限制有些数无法有限表示。就像一些无理数不能有限表示,如 圆周率 3.1415926...,1.3333... 等。JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit

  • 1位用来表示符号位
  • 11位用来表示指数
  • 52位表示尾数

比如:

0.1 >> 0.0001 1001 1001 1001…(1001无限循环)0.2 >> 0.0011 0011 0011 0011…(0011无限循环)

此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。

大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即 9007199254740992。

9007199254740992 + 1 // 丢失9007199254740992 + 2 // 未丢失9007199254740992 + 3 // 丢失9007199254740992 + 4 // 未丢失

大于 9007199254740992 的可能会丢失精度,看似有穷的数字, 在计算机的二进制表示里却是无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了

2.如何解决

2.1

在每次计算的时候把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数) 例:

2.2

第一种每次计算都要重复的去乘以和除以使得代码不美观,将下面方法封装到utils工具中每次使用时去调用就可以了,这几个方法原理上其实和第一种差不多的

//除法function accDiv(arg1,arg2){    var t1=0,t2=0,r1,r2;    try{t1=arg1.toString().split(".")[1].length}catch(e){}    try{t2=arg2.toString().split(".")[1].length}catch(e){}    with(Math){     r1=Number(arg1.toString().replace(".",""))     r2=Number(arg2.toString().replace(".",""))     return accMul((r1/r2),pow(10,t2-t1));   } }     //乘法 function accMul(arg1,arg2){   var m=0,s1=arg1.toString(),s2=arg2.toString();   try{m+=s1.split(".")[1].length}catch(e){}   try{m+=s2.split(".")[1].length}catch(e){}   return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m) }//加法function accAdd(arg1,arg2){   var r1,r2,m;   try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}   try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}   m=Math.pow(10,Math.max(r1,r2))   return (arg1*m+arg2*m)/m}//减法function Subtr(arg1,arg2){   var r1,r2,m,n;   try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}   try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}   m=Math.pow(10,Math.max(r1,r2));   n=(r1>=r2)?r1:r2;   return ((arg1*m-arg2*m)/m).toFixed(n);}// console.log(accMul(0.0003,10000))// console.log(0.0003*10000)

// console.log(Subtr(0.999,0.998))// console.log(0.999-0.998)

// console.log(accMul(0.0035,100))// console.log(0.0035*100)

// console.log(accDiv(0.3,0.2))// console.log(0.3/0.2)

2.3

引入一些处理数字运算的库,比如 Math.js 再去调用它提供出来的方法,个人认为如果项目没有要前端去处理金额之类的可以不用这种



js浮点数运算不精确 如何解决_解决 浏览器处理数字运算时精度丢失的方法相关推荐

  1. JSON long 型 数字过长精度丢失解决

    目录 1. 引入JacksonObjectMapper 2. 在WebMvcConfig中重写方法extendMessageConverters 由于在SpringMVC中, 将Controller方 ...

  2. 解决Vue 前端Long型超过16位精度丢失问题

    问题描述 后端利用雪花算法生成id前端接受时候精度会丢失, 这是idea控制台打印的id 这是在数据库里的id 很明显后面几位数做处理了,不过不用慌这个问题还是很简单的下面我来说下我的解决方案 解决方 ...

  3. js long类型精度丢失_后端Long类型传到前端精度丢失的正确解决方式

    原因:前端js对Long类型支持的精度不够,导致后端使用的Long传到前端丢失精度,比如现在分布式id生成算法"雪花算法"在使用中就会出现问题. 解决方式: 1.后端的Long类型 ...

  4. 解决js获取当前时间精确到秒并格式划成数字(20200712120610)

    //获取当前时间格式成数字型getCurrentTime() {let date = new Date(); //当前标准时间格式let year = date.getFullYear(); //取得 ...

  5. python打印自动换行如何解决_解决python DataFrame 打印结果不换行问题

    解决python DataFrame 打印结果不换行问题 如下所示: 加入代码: pd.set_option('display.width', 5000) 补充知识:Python 实现不换行打印字符的 ...

  6. 错误代码0x800f0950怎么解决_解决win10安装net framework 3.5失败(错误代码 0x800F0950)...

    视频教程: Win10教程 安装net framework 3.5失败(错误代码 0x800F0950)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com 一:出现 ...

  7. hashmap是线程安全的吗?怎么解决?_解决SimpleDateFormat线程安全问题

    SimpleDateFormat是线程不安全的类,一般不要定义为static变量,如果定义为static,必须通过加锁等方式保证线程安全. 例如下面一段代码,启动10个线程,同时使用一个`Simple ...

  8. java跨用问题怎么解决_跨浏览器问题的五种解决方案

    c编程技巧-117个问题解决方案示例 79.2元 包邮 (需用券) 去购买 > 简评:浏览器兼容性问题常常让人头疼,以下是避免出现这些问题的五个技巧. 1. 前缀 CSS3 样式 如果您正在使用 ...

  9. 小程序引入的echarts过大如何解决_解决微信小程序引用echarts视图模糊的问题

    function initChart(canvas, width, height,dpr) { const chart = echarts.init(canvas, null, { width: wi ...

最新文章

  1. MySQL 学习笔记(13)— 创建表、修改表、删除表、清空表
  2. JAVA WEB开发环境与搭建
  3. Audition 2020安装教程
  4. MRCTF2020]你传你码呢
  5. 数据中台建设中的得与失
  6. linux下面的chrome总是跳出xdg-open怎么办
  7. android各种color值
  8. U盘流畅运行linux发行版,做各种linux发行版的启动U盘方法
  9. shell 脚本空行造成 :not found make.sh:
  10. 微软为一人收购一公司?破解索尼程序、写黑客小说,看他彪悍的程序人生!...
  11. elementui的表格在使用v-if之后列的顺序错乱问题
  12. CAM350 12.1版本安装
  13. 自然语言处理-错字识别(基于Python)kenlm、pycorrector
  14. 实战 Flutter 象棋从零到上架
  15. navicat如何创建数据库及如何导入数据库文件【初学者适用】
  16. 技术面试(一)认识技术面试
  17. 参数估计的均方误差(MSE),偏置(Bias)与方差(Variance)分解,无偏估计
  18. 分享五款没什么名气却意外好用的软件
  19. Mac上将mp4视频做成屏保
  20. 工作仅一年就被迫跳槽的感想

热门文章

  1. Hyperledger Fabric 智能合约实战 (5) go语言开发
  2. java元婴期(25)----java进阶(mybatis(4)---高级映射查询缓存)
  3. 创新实训个人记录:P versus NP
  4. 公钥密码体制(RSA,椭圆曲线密码,ElGamal
  5. (49)逆向分析KiSystemService/KiFastCallEntry调用内核函数部分(SST,SSDT,SSPT)
  6. 【安全漏洞】利用CodeQL分析并挖掘Log4j漏洞
  7. Windbg无源码调试驱动
  8. 5、数据库设计的三大范式
  9. Codeforces Round #486 (Div. 3)【完结】
  10. 【PAT乙级】1072 开学寄语 (20 分)