JavaScript 浮点数运算精度问题与解决方案

作者:代码拾荒

时间:2026-10-24

浏览:295

本文深入解析JavaScript中浮点数运算产生精度误差的根本原因,并提供了一套完整的解决方案。通过介绍将浮点数转换为整数进行运算再还原的方法,实现了高精度的加法、减法、乘法和除法函数。此外,文章还展示了如何扩展Number原型以简化调用,确保金融或高精度场景下的计算准确性。

文章目录

JavaScript 浮点数运算精度问题与解决方案

JavaScript 代码示例


具体实现如下:

 
<script type="text/javascript" language="javascript">
alert(1/3);//显示: 0.3333333333333333
alert(0.09999999 + 0.00000001);//显示: 0.09999999999999999
alert(-0.09999999 - 0.00000001);//显示: -0.09999999999999999
alert(0.012345 * 0.000001);//显示: 1.2344999999999999e-8
alert(0.000001 / 0.0001);//显示: 0.009999999999999998
</script>
<script type="text/javascript" language="javascript">
alert(1/3);//显示: 0.3333333333333333
alert(0.09999999 + 0.00000001);//显示: 0.09999999999999999
alert(-0.09999999 - 0.00000001);//显示: -0.09999999999999999
alert(0.012345 * 0.000001);//显示: 1.2344999999999999e-8
alert(0.000001 / 0.0001);//显示: 0.009999999999999998
</script>
[code]
理论上,除首行(因无法整除)外,其余运算应得精确值,但实际输出存在偏差。为修正浮点数运算精度误差,可在计算前将数值放大10的X次方至整数,运算后再缩小0.1的X次方。此处整理相关方案供后续参考。
加法加法运算
JavaScript 代码片段
[code]
//说明: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);
} 
//说明: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);
} 
减法减法运算
JavaScript 代码片段
[code]
//说明:javascript的减法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
//调用:accSub(arg1,arg2)
//返回值:arg1减上arg2的精确结果
function accSub(arg1,arg2){
return accAdd(arg1,-arg2);
} 
//给Number类型增加一个sub方法,调用起来更加方便。
Number.prototype.sub = function (arg){
return accSub(this,arg);
} 
//说明:javascript的减法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
//调用:accSub(arg1,arg2)
//返回值:arg1减上arg2的精确结果
function accSub(arg1,arg2){
return accAdd(arg1,-arg2);
} 
//给Number类型增加一个sub方法,调用起来更加方便。
Number.prototype.sub = function (arg){
return accSub(this,arg);
} 

乘法

乘法运算


JavaScript 代码片段


具体实现如下:

 
//说明: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的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
//调用: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 代码片段
//说明: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的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
//调用: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 代码片段


具体实现如下:

 
<script type="text/javascript" language="javascript">
/* 
alert(0.09999999 + 0.00000001);//显示: 0.09999999999999999
alert(-0.09999999 - 0.00000001);//显示: -0.09999999999999999
alert(0.012345 * 0.000001);//显示: 1.2344999999999999e-8
alert(0.000001 / 0.0001);//显示: 0.009999999999999998
*/ 
alert(0.09999999.add(0.00000001));//显示: 0.1
alert(-0.09999999.sub(0.00000001));//显示: -0.09999998
alert(0.012345.mul(0.000001));//显示: 1.2345e-8
alert(0.000001.div(0.0001));//显示: 0.01
</script>

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章