解决JS浮点数运算出现Bug的方法


Posted in Javascript onMarch 12, 2013

37.5*5.5=206.08 (JS算出来是这样的一个结果,我四舍五入取两位小数)
我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998
怎么会这样,两个只有一位小数的数字相乘,怎么可能多出这么小数点出来。
我Google了一下,发现原来这是JavaScript浮点运算的一个bug。
比如:7*0.8 JavaScript算出来就是:5.6000000000000005

网上找到了一些解决办法,就是重新写了一些浮点运算的函数或直接扩大倍数运算。
下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:

//除法函数,用来得到精确的除法结果 
//说明: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); 
} 
//减法函数,用来得到精确的减法结果 
//说明:javascript的减法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。 
//调用:accSubtr(arg1,arg2) 
//返回值:arg1减去arg2的精确结果 
function accSubtr(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);
} 
//给Number类型增加一个subtr 方法,调用起来更加方便。 
Number.prototype.subtr = function (arg){ 
return accSubtr(arg,this); 
}

在你要用的地方包含这些函数,然后调用它来计算就可以了。

/如果在知道小数位个数的前提下,可以考虑通过将浮点数放大倍数到整型(最后再除以相应倍数),再进行运算操作,这样就能得到正确的结果了

<script> 
alert(11*(22.9*10)/10);
</script>
Javascript 相关文章推荐
Javascript YUI 读码日记之 YAHOO.util.Dom - Part.2 0
Mar 22 Javascript
javascript同步Import,同步调用外部js的方法
Jul 08 Javascript
初识JQuery 实例一(first)
Mar 16 Javascript
jQuery中$.fn的用法示例介绍
Nov 05 Javascript
JS实现支持多选的遍历下拉列表代码
Aug 20 Javascript
js实现简单折叠、展开菜单的方法
Aug 28 Javascript
整理Javascript流程控制语句学习笔记
Nov 29 Javascript
JavaScript函数内部属性和函数方法实例详解
Mar 17 Javascript
JS 中LocalStorage和SessionStorage的使用
Aug 17 Javascript
vue项目中使用ueditor的实例讲解
Mar 05 Javascript
boostrap模态框二次弹出清空原有内容的方法
Aug 10 Javascript
webpack-mvc 传统多页面组件化开发详解
May 07 Javascript
JS实现悬浮移动窗口(悬浮广告)的特效
Mar 12 #Javascript
js弹出模式对话框,并接收回传值的方法
Mar 12 #Javascript
js 获取class的元素的方法 以及创建方法getElementsByClassName
Mar 11 #Javascript
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
Mar 11 #Javascript
JS中Iframe之间传值的方法
Mar 11 #Javascript
JS中Iframe之间传值及子页面与父页面应用
Mar 11 #Javascript
js将iframe中控件的值传到主页面控件中的实现方法
Mar 11 #Javascript
You might like
《APMServ 5.1.2》使用图解
2006/10/23 PHP
Paypal实现循环扣款(订阅)功能
2017/03/23 PHP
javascript之函数直接量(function(){})()
2007/06/29 Javascript
jQuery ajax cache缓存问题
2010/07/01 Javascript
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
2011/11/30 Javascript
jquery延迟加载外部js实现代码
2013/01/11 Javascript
jquery实现页面关键词高亮显示的方法
2015/03/12 Javascript
在 Express 中使用模板引擎
2015/12/10 Javascript
JS动态的把左边列表添加到右边的实现代码(可上下移动)
2016/11/17 Javascript
JS实现点击链接切换显示隐藏内容的方法
2017/10/19 Javascript
JS返回顶部实例代码
2020/08/09 Javascript
微信小程序调用摄像头隐藏式拍照功能
2018/08/22 Javascript
js实现input密码框显示/隐藏功能
2020/09/10 Javascript
微信小程序实现多选删除列表数据功能示例
2019/01/15 Javascript
Bootstrap 时间日历插件bootstrap-datetimepicker配置与应用小结
2019/05/28 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
vue prop属性传值与传引用示例
2019/11/13 Javascript
JS快速实现简单计算器
2020/04/08 Javascript
[38:39]KG vs Mineski 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/16 DOTA
python爬取网站数据保存使用的方法
2013/11/20 Python
python获取Linux下文件版本信息、公司名和产品名的方法
2014/10/05 Python
python读取excel表格生成erlang数据
2017/08/26 Python
python在非root权限下的安装方法
2018/01/23 Python
Python使用pickle模块实现序列化功能示例
2018/07/13 Python
python命令 -u参数用法解析
2019/10/24 Python
解决pyshp UnicodeDecodeError的问题
2019/12/06 Python
Python数组拼接np.concatenate实现过程
2020/04/18 Python
amazeui页面校验功能的实现代码
2020/08/24 HTML / CSS
英国汽车座椅和婴儿车购物网站:Uber Kids
2017/04/19 全球购物
Peter Millar官网:美国高档生活服饰品牌
2018/07/02 全球购物
医学专业毕业生求职信
2014/06/20 职场文书
2014乡镇党政班子四风问题思想汇报
2014/09/14 职场文书
朋友聚会开场白
2015/06/01 职场文书
女方家长婚礼致辞
2015/07/27 职场文书
二胎满月酒致辞
2015/07/29 职场文书
python获取带有返回值的多线程
2022/05/02 Python