JavaScript小数乘除法精度问题与解决方案

作者:木棉

时间:2026-10-28

浏览:585

JavaScript在处理小数乘除法时存在浮点数精度丢失的Bug,导致结果出现大量尾数。本文通过扩大倍数转为整数计算的方法解决常规误差,并提供了accDiv、accMul、accAdd等精确运算函数的完整代码实现,通过扩展Number原型方便调用,确保财务等场景的计算准确性。

文章目录

JavaScript小数计算精度问题现象

使用JavaScript进行计算时,例如12.32乘以7,得到的结果并非预期的86.24,而是86.24000000000001。

造成这种现象的原因是JavaScript在处理小数乘除法时存在固有的Bug。解决思路是将小数转换为整数进行运算。例如,将原式改为12.32乘以100再乘以7,最后除以100,即可得到正确的结果86.24。

然而,这种方法并非对所有数字都有效。例如计算8.80乘以100再乘以12除以100,结果仍为105.60000000000002。类似地,38.80的计算也会出现相同的问题。

精度提升至10倍: 8.80 * 1000 * 12 / 1000 结果:105.6 恢复正常。

继续增加倍数,如16.40乘以1000000再乘以6除以1000000,结果依然会出现误差。

经过测试,将数值扩大10000倍再除以10000是较为稳妥的处理方式,能有效解决大多数小数计算问题。示例代码如下:var num = 38.80; var num2 = 13; alert(num * 10000 * 12 / 10000);

测试表明,乘除的倍数设为10000最为合适。倍数过小会导致部分数字出现误差,而倍数过大(如1000000)同样会引发某些数字的计算错误。

基于Number原型的解决方案

以下是另一种解决思路的代码实现。

代码如下:

<script defer>
Number.prototype.rate=function(){
var oStr=this.toString();
if(oStr.indexOf(".")==-1)
return 1;
else
return Math.pow(10,parseInt(oStr.length-oStr.indexOf(".")-1));
}
}
function tran(){
args=tran.arguments;
var temp=1;
for(i=0;i<args.length;i++)
temp*=args[i]*args[i].rate();
for(i=0;i<args.length;i++)
temp/=args[i].rate();
return temp
}
alert(tran(11,22.9));
</script>

该方法虽然较为繁琐,但能清晰展示解决小数精度问题的实际过程。


精确加减乘除函数实现

代码如下:

//除法函数,用来得到精确的除法结果
//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用:accDiv(arg1,arg2)
//返回值:arg1除以arg2的精确结果
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 (r1/r2)*pow(10,t2-t1);
}
}
}
//给Number类型增加一个div方法,调用起来更加方便。
Number.prototype.div = function (arg){
return accDiv(this, arg);
}
//乘法函数,用来得到精确的乘法结果
//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用:accMul(arg1,arg2)
//返回值:arg1乘以 arg2的精确结果
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)
}
// 给Number类型增加一个mul方法,调用起来更加方便。
Number.prototype.mul = function (arg){
return accMul(arg, this);
}
//加法函数,用来得到精确的加法结果
//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
//调用:accAdd(arg1,arg2)
// 返回值:arg1加上arg2的精确结果
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
}
//给Number类型增加一个add方法,调用起来更加方便。
Number.prototype.add = function (arg){
return accAdd(arg,this);
}

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章