JS的计算时精度丢失问题

JavaScript07

JS的计算时精度丢失问题,第1张

如:0.1+0.2 !== 0.3;0.1*0.2 !== 0.03

如:9999999999999999 === 10000000000000001

如:1.335.toFixed(2) // 1.33;1.336.toFixed(2) // 1.34

二进制模仿十进制进行四舍五入,而二进制只有0和1,于是就0舍1入,于是就导致了小数计算不精确。大数的精度丢失本质上是和小数一样,js中表示最大的数是Math.pow(2, 53),十进制即 9007199254740992;大于该数的值可能会丢失精度。

小数的话,一般转成整数进行计算,然后对结果做除法;同样也可以直接对结果进行4舍5入;

对于大数出现的问题概率较低,毕竟还要运算结果不超过最大数就不会丢失精度;

javaScript数字精度丢失问题总结

js中精度问题以及解决方案

JavaScript 中精度问题以及解决方案

以上方法可以解决js 与 controller、前台controller 与 后台controller 之间大数字传输精度丢失问题。缺点是每个用到大数字的实体都需要进行配置。

本文所有方法只能解决传输过程、js 接收数据精度丢失问题。不能解决前台Js大数字运算精度丢失问题,大数字运算最好放到Java中。

方法一: 解决反序列化时,BigDecimal类型精度缺失

PmServiceServiceApplication.java 增加如下配置

此方法可以解决前台controller 到后台controller ,反序列化时数字精度丢失问题,也可以修改其他数据类型的格式。

方法二: 解决Js json字符串转换为js对象时精度缺失

用正则匹配json中的12位以上数字,替换为字符串。

以当前项目为例:修改前台 ajaxdatawrap.js 中convertJsonToDC方法,用正则表达式匹配每个大于12位的数字,替换为字符串。

此方法可以解决js接收到controller数据之后,转为js对象时,精度丢失问题(列表页面中,前台controller所接收大数字字段精度已经丢失,与js无关)。

缺点:不准确(小概率,正则表达式有可能替换掉不是数字但是符合条件的数据)

//浮点数加法运算

function FloatAdd(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 FloatSub(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)

}

//浮点数乘法运算

function FloatMul(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 FloatDiv(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 (r1/r2)*pow(10,t2-t1)

}

}

===============================================

1.丢弃小数部分,保留整数部分parseInt(5/2)

2.向上取整,有小数就整数部分加1

Math.ceil(5/2)

3,四舍五入.

Math.round(5/2)

4,向下取整

Math.floor(5/2)