javascript避免数字计算精度误差的方法详解


Posted in Javascript onMarch 05, 2014

如果我问你 0.1 + 0.2 等于几?你可能会送我一个白眼,0.1 + 0.2 = 0.3 啊,那还用问吗?连幼儿园的小朋友都会回答这么小儿科的问题了。但是你知道吗,同样的问题放在编程语言中,或许就不是想象中那么简单的事儿了。
不信?我们先来看一段 JS。

var numA = 0.1;
var numB = 0.2;
alert( (numA + numB) === 0.3 );

执行结果是 false。没错,当我第一次看到这段代码时,我也理所当然地以为它是 true,但是执行结果让我大跌眼镜,是我的打开方式不对吗?非也非也。我们再执行以下代码试试就知道结果为什么是 false 了。

var numA = 0.1;
var numB = 0.2;
alert( numA + numB );

原来,0.1 + 0.2 = 0.30000000000000004。是不是很奇葩?其实对于浮点数的四则运算,几乎所有的编程语言都会有类似精度误差的问题,只不过在 C++/C#/Java 这些语言中已经封装好了方法来避免精度的问题,而 JavaScript 是一门弱类型的语言,从设计思想上就没有对浮点数有个严格的数据类型,所以精度误差的问题就显得格外突出。下面就分析下为什么会有这个精度误差,以及怎样修复这个误差。

首先,我们要站在计算机的角度思考 0.1 + 0.2 这个看似小儿科的问题。我们知道,能被计算机读懂的是二进制,而不是十进制,所以我们先把 0.1 和 0.2 转换成二进制看看:

0.1 => 0.0001 1001 1001 1001…(无限循环)
0.2 => 0.0011 0011 0011 0011…(无限循环)

双精度浮点数的小数部分最多支持 52 位,所以两者相加之后得到这么一串 0.0100110011001100110011001100110011001100110011001100 因浮点数小数位的限制而截断的二进制数字,这时候,我们再把它转换为十进制,就成了 0.30000000000000004。

原来如此,那怎么解决这个问题呢?我想要的结果就是 0.1 + 0.2 === 0.3 啊!!!

有种最简单的解决方案,就是给出明确的精度要求,在返回值的过程中,计算机会自动四舍五入,比如:

var numA = 0.1;
var numB = 0.2;
alert( parseFloat((numA + numB).toFixed(2)) === 0.3 );

但是明显这不是一劳永逸的方法,如果有一个方法能帮我们解决这些浮点数的精度问题,那该多好。我们来试试下面这个方法:

Math.formatFloat = function(f, digit) {
    var m = Math.pow(10, digit);
    return parseInt(f * m, 10) / m;
}

var numA = 0.1;
var numB = 0.2;

alert(Math.formatFloat(numA + numB, 1) === 0.3);

这个方法是什么意思呢?为了避免产生精度差异,我们要把需要计算的数字乘以 10 的 n 次幂,换算成计算机能够精确识别的整数,然后再除以 10 的 n 次幂,大部分编程语言都是这样处理精度差异的,我们就借用过来处理一下 JS 中的浮点数精度误差。

如果下次再有人问你 0.1 + 0.2 等于几,你可要小心回答咯!!

Javascript 相关文章推荐
JavaScipt基本教程之JavaScript语言的基础
Jan 16 Javascript
JScript中使用ADODB.Stream判断文件编码的代码
Jun 09 Javascript
Javascript setInterval的两种调用方法(实例讲解)
Nov 29 Javascript
Visual Studio中js调试的方法图解
Jun 30 Javascript
node.js中的http.response.writeHead方法使用说明
Dec 14 Javascript
js实现input框文字动态变换显示效果
Aug 19 Javascript
js+canvas绘制矩形的方法
Jan 28 Javascript
jQuery实现字体颜色渐变效果的方法
Mar 29 jQuery
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
Aug 20 Javascript
解决Layui中layer报错的问题
Sep 03 Javascript
《javascript设计模式》学习笔记五:Javascript面向对象程序设计工厂模式实例分析
Apr 08 Javascript
微信小程序自定义tabBar的踩坑实践记录
Nov 06 Javascript
javascript/jquery获取地址栏url参数的方法
Mar 05 #Javascript
js离开或刷新页面检测(且兼容FF,IE,Chrome)
Mar 05 #Javascript
js特殊字符过滤的示例代码
Mar 05 #Javascript
jquerymobile局部渲染的各种刷新方法小结
Mar 05 #Javascript
JqueryMobile动态生成listView并实现刷新的两种方法
Mar 05 #Javascript
jquery mobile动态添加元素之后不能正确渲染解决方法说明
Mar 05 #Javascript
thinkphp中常用的系统常量和系统变量
Mar 05 #Javascript
You might like
php jquery 实现新闻标签分类与无刷新分页
2009/12/18 PHP
PHP 字符串长度判断效率更高的方法
2014/03/02 PHP
使用ucenter实现多站点同步登录的讲解
2019/03/21 PHP
音乐播放用的的几个函数
2006/09/07 Javascript
jQuery表单验证插件formValidator(改进版)
2012/02/03 Javascript
关于jQuery新的事件绑定机制on()的使用技巧
2013/04/26 Javascript
etmvc+jQuery EasyUI+combobox多值操作实现角色授权实例
2016/11/09 Javascript
基于vue.js实现图片轮播效果
2016/12/01 Javascript
jquery hover 不停闪动问题的解决方法(亦为stop()的使用)
2017/02/10 Javascript
layui+SSM的数据表的增删改实例(利用弹框添加、修改)
2019/09/27 Javascript
Python ORM框架SQLAlchemy学习笔记之映射类使用实例和Session会话介绍
2014/06/10 Python
python实现复制整个目录的方法
2015/05/12 Python
Python制作钉钉加密/解密工具
2016/12/07 Python
Python内存读写操作示例
2018/07/18 Python
Python使用logging模块实现打印log到指定文件的方法
2018/09/05 Python
Pytorch实现GoogLeNet的方法
2019/08/18 Python
Python *args和**kwargs用法实例解析
2020/03/02 Python
python模拟实现分发扑克牌
2020/04/22 Python
解决pytorch多GPU训练保存的模型,在单GPU环境下加载出错问题
2020/06/23 Python
Python pymsql模块的使用
2020/09/07 Python
linux mint中搜狗输入法导致pycharm卡死的问题
2020/10/28 Python
python eventlet绿化和patch原理
2020/11/21 Python
关于多种方式完美解决Python pip命令下载第三方库的问题
2020/12/21 Python
canvas绘制树形结构可视图形的实现
2020/04/03 HTML / CSS
全球度假村:Club Med
2017/11/27 全球购物
澳大利亚珠宝商:Shiels
2019/10/06 全球购物
竞聘医务工作人员的自我评价分享
2013/11/04 职场文书
会计电算化学生个人的自我评价
2014/02/08 职场文书
《巨人的花园》教学反思
2014/02/12 职场文书
硕士研究生就业推荐信
2014/05/18 职场文书
公安个人四风问题对照检查及整改措施
2014/10/28 职场文书
2015年全国爱眼日活动小结
2015/02/27 职场文书
同学聚会通知书
2015/04/20 职场文书
导游词之金鞭溪风景区
2019/09/12 职场文书
你有一份《诚信考试承诺书》待领取
2019/11/13 职场文书
Python爬虫之爬取二手房信息
2021/04/27 Python