解决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 模仿vbs中的 DateAdd() 函数的代码
Aug 13 Javascript
Prototype 学习 工具函数学习($w,$F方法)
Jul 12 Javascript
基于jQuery的简单的列表导航菜单
Mar 02 Javascript
js 输出内容到新窗口具体实现代码
May 31 Javascript
如何使用jQuery Draggable和Droppable实现拖拽功能
Jul 05 Javascript
AngularJS入门教程(零):引导程序
Dec 06 Javascript
js获取Html元素的实际宽度高度的方法
May 19 Javascript
网页挂马方式整理及详细介绍
Nov 03 Javascript
详解Angular2响应式表单
Jun 14 Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
Dec 03 Javascript
前端天气插件tpwidget使用方法详解
Jun 24 Javascript
JS实现网页烟花动画效果
Mar 10 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
PHP错误Allowed memory size of 67108864 bytes exhausted的3种解决办法
2014/07/28 PHP
PHP基于递归算法解决兔子生兔子问题
2018/05/11 PHP
js 操作css实现代码
2009/06/11 Javascript
疯狂Jquery第一天(Jquery学习笔记)
2012/05/11 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
实例讲解JavaScript的Backbone.js框架中的View视图
2016/05/05 Javascript
JavaScript必知必会(二) null 和undefined
2016/06/08 Javascript
详解用node编写自己的cli工具
2017/05/23 Javascript
JS中定位 position 的使用实例代码
2017/08/06 Javascript
JS排序算法之冒泡排序,选择排序与插入排序实例分析
2017/12/13 Javascript
Vue 实现列表动态添加和删除的两种方法小结
2018/09/07 Javascript
JavaScript循环遍历你会用哪些之小结篇
2018/09/28 Javascript
深入解析ES6中的promise
2018/11/08 Javascript
ES6 迭代器与可迭代对象的实现
2019/02/11 Javascript
vue-cli3添加模式配置多环境变量的方法
2019/06/05 Javascript
Vue 中 filter 与 computed 的区别与用法解析
2019/11/21 Javascript
js实现上下左右键盘控制div移动
2020/01/16 Javascript
Vue过渡效果之CSS过渡详解(结合transition,animation,animate.css)
2020/02/05 Javascript
详解Nuxt内导航栏的两种实现方式
2020/04/16 Javascript
[03:00]《DAC最前线》之欧美新秀VS老将
2015/02/01 DOTA
python发送邮件示例(支持中文邮件标题)
2014/02/16 Python
centos6.4下python3.6.1安装教程
2017/07/21 Python
Django重装mysql后启动报错:No module named ‘MySQLdb’的解决方法
2018/04/22 Python
用Python实现校园通知更新提醒功能
2019/11/23 Python
Python使用QQ邮箱发送邮件实例与QQ邮箱设置详解
2020/02/18 Python
django model通过字典更新数据实例
2020/04/01 Python
Python利用for循环打印星号三角形的案例
2020/04/12 Python
详解python爬取弹幕与数据分析
2020/11/14 Python
CSS3 三维变形实现立体方块特效源码
2016/12/15 HTML / CSS
html5组织内容_动力节点Java学院整理
2017/07/10 HTML / CSS
what is the difference between ext2 and ext3
2015/08/25 面试题
声乐专业大学生职业生涯规划书:理想的未来需要自己去打造
2014/09/20 职场文书
六一儿童节开幕词
2015/01/29 职场文书
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
2021/05/25 Vue.js
JavaScript高级程序设计之变量与作用域
2021/11/17 Javascript
一文了解Java动态代理的原理及实现
2022/07/07 Java/Android