手机版

解决JavaScript中数字精度损失问题的方法

时间:2021-09-21 来源:互联网 编辑:宝哥软件园 浏览:

本文分为三个部分。

JS数字精度损失的几个典型问题?JS数字精度损失的原因及解决方法(一个对象一个功能)一、JS数字精度损失的一些典型问题。

1.添加两个简单的浮点数。

0.1 0.2 !=0.3 //真

这真的不是Firebug的问题。可以带着警惕试试(哈哈,开玩笑的)。

看看Java的计算结果。

再看看Python。

2.大整数运算。

16位数和17位数是偶数是不合理的。

另一个例子是

var x=9007199254740992x 1==x /?看看结果

三观再次被颠覆。

3.toFixed不会被舍入(Chrome)。

Chrome和其他浏览器的在线价格不一致。

二、JS数字丢失准确性的原因。

计算机二进制实现和位限制。有些数字不能用有限的方式表达。就像有些无理数不能用有限项表示一样,比如pi 3.1415926,pi 1.3333等。按照IEEE 754标准,JS采用双精度,占用64位。数字

意义

例如,1位用于符号,11位用于指数,52位用于尾数浮点数。

0.1 0.0001 1001 1001 .(1001无限循环)0.2 0.0011 0011 0011.(0011无限循环)此时只能模仿十进制四舍五入,但二进制只有0和1两种,所以就变成了0和1。这就是为什么计算机中的一些浮点数有错误而失去准确性的根本原因。

大整数的精度损失和浮点数的精度损失本质上是一样的,最大尾数位是52位,所以在JS中可以精确表示的最大整数是Math.pow(2,53),十进制是9007199254740992。

大于9007199254740992可能会失去准确性。

007199254740992 100000000000 .000//总共53 09007199254740992 1 10000000000000.001//中间52 09007199254740992 2 2 1000000000000。

9007199254740992 1 //缺失900719925474092 2//未缺失900719925474092 3//缺失900719925474092 4//未缺失结果如图所示。

从上面可以知道,在计算机的二进制表示中,看似有限的数是无限的。由于存储位数的限制,出现了“丢弃”,出现了精度损失。

第三,解决方案

对于整数,前端出现问题的概率可能比较低。毕竟需要用到很大整数的业务很少,只要运算结果不超过Math.pow(2,53)就不会丢失精度。

对于小数来说,还是有很多前端问题的,尤其是一些涉及金额等数据的电商网站。解决方法:将十进制数转化为整数(乘以倍数),然后还原为原来的倍数(倍数除外)。

//0.1 0.2(0.1 * 10 0.2 * 10)/10==0.3//true下面是我写的一个对象,它掩盖了十进制加减乘除丢失的精度。当然,转换后的整数还是不能超过9007199254740992。

/** *浮点j包含加减乘除四个方法,能确保浮点数运算不丢失精度* * 我们知道计算机编程语言里浮点数计算会存在精度丢失问题(或称舍入误差),其根本原因是二进制和实现位数限制有些数无法有限表示* 以下是十进制小数对应的二进制表示* 0.1 0.0001 1001 1001 1001…(1001无限循环) * 0.2 0.0011 0011 0011 0011…(0011无限循环) * 计算机里每种数据类型的存储是一个有限宽度,比如Java脚本语言使用64 位存储数字类型,因此超出的会舍去。舍去的部分就是精度丢失的部分* * **方法* * *加/减/乘/除* * * * exp ame * * * 0.1 0.2==0.3000000000004(多了0.00000000000004) * 0.2 0.4==0.6000000000000001 (多了0.0000000000001) * 19.9 * 100==1989.9999999999998 (少了0.00000000000002)* * float tobj。添加(0.1,0.2)0.3 * float tobj。乘(19.9,100)1990 * */var float tobj=function(){/* * *判断目标文件是否为一个整数*/函数是integer(obj){ return math。地板(obj)==obj }/* *将一个浮点数转成整数,返回整数和倍数。如3.14 314,倍数是100 * @param floatNum {number}小数* @将{ object } * { times :100,num 3360 314 } */函数返回到integer(float num){ var ret={ times : 0,num : 0 0 } if(is integer(float num)){ ret。num=float num ret } var strfi=float num ' ' var dot pos=strfi。'的索引.)var len=strfi.substr(dotPos 1).length var乘以=Math.pow(10,len)var intNum=parsent(float num *乘以0.5,10)ret。时间=时间ret。num=intNum ret }/* *核心方法,实现加减乘除运算,确保不丢失精度* 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)* * @param a {number}运算数1 * @param b {number}运算数2 * @参数数字{number}精度,保留的小数点数,比如2, 即保留为两位小数* @param op {string}运算类型,有加减乘除(加/减/乘/除)* */函数运算(a,b,数字,op){ var O1=to integer(a)var O2=to integer(b)var max=O1O2?o1。乘以: o2。乘以定义变量结果=null switch(op){ case ' add ' :结果=O1。O2的数量。'中断案例数'减法:结果=O1。num-O2。'中断案例数'乘法:结果=O1。num * O2。num break case ' divide ' :结果=O1。数量/O2。num break }返回结果/最大值}//加减乘除的四个接口函数添加(a,b,位数){返回操作(a,b,位数、“添加”)}函数减法(a,b,位数){返回操作(a,b,位数,'减法')}函数乘法(a,b,位数){返回操作(a,b,位数,乘法')}函数除(a,b,数字){返回运算(a,b,数字,'除')} //导出返回{ add: add,减法:减法,多倍:乘法,divide : divide } });

至固定的修复如下

//toFixed修复函数toFixed(num,s) { var times=Math.pow(10,s)var des=num * times 0.5 des=parsent(des,10)/times return des ''}以上就是关于Java脚本语言数字精度丢失问题全部内容,对典型问题进行分析,分析数字精度丢失原因,还分享了解决方案,希望对大家的学习有所帮助。

版权声明:解决JavaScript中数字精度损失问题的方法是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐