如: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)