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 相关文章推荐
jQuery图片预加载 等比缩放实现代码
Oct 04 Javascript
JavaScript NodeTree导航栏(菜单项JSON类型/自制)
Feb 01 Javascript
angularJS中router的使用指南
Feb 09 Javascript
jquery实现简单的无缝滚动
Apr 15 Javascript
基于jquery实现的树形菜单效果代码
Sep 06 Javascript
原生js仿浏览器滚动条效果
Mar 02 Javascript
微信小程序中页面FOR循环和嵌套循环
Jun 21 Javascript
详解组件库的webpack构建速度优化
Jun 18 Javascript
利用jqgrid实现上移下移单元格功能
Nov 07 Javascript
vue项目实现图片上传功能
Dec 23 Javascript
jquery.validate自定义验证用法实例分析【成功提示与择要提示】
Jun 06 jQuery
原生JS实现天气预报
Jun 16 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代码中使用换行及(\n或\r\n和br)的应用
2013/02/02 PHP
php过滤html中的其他网站链接的方法(域名白名单功能)
2014/04/24 PHP
Codeigniter出现错误提示Error with CACHE directory的解决方案
2014/06/12 PHP
PHP+mysql实现从数据库获取下拉树功能示例
2017/01/06 PHP
php-app开发接口加密详解
2018/04/18 PHP
Javascript笔记一 js以及json基础使用说明
2010/05/22 Javascript
JSCode all of Brower 全局屏蔽网页右键功能 具体实现
2013/06/05 Javascript
js获取url参数值的两种方式
2013/09/10 Javascript
js获取input长度并根据页面宽度设置其大小及居中对齐
2014/08/22 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
Bootstrap Table服务器分页与在线编辑应用总结
2016/08/08 Javascript
Google 爬虫如何抓取 JavaScript 的内容
2017/04/07 Javascript
利用node.js实现自动生成前端项目组件的方法详解
2017/07/12 Javascript
JavaScript闭包的简单应用
2017/09/01 Javascript
JavaScript实现求最大公共子串的方法
2018/02/03 Javascript
JS滚轮控制图片缩放大小和拖动的实例代码
2018/11/20 Javascript
Typescript的三种运行方式(小结)
2019/09/18 Javascript
使用js原生实现年份轮播选择效果实例
2021/01/12 Javascript
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
[01:08:57]2014 DOTA2国际邀请赛中国区预选赛 5 23 CIS VS LGD第二场
2014/05/24 DOTA
使用python提取html文件中的特定数据的实现代码
2013/03/24 Python
利用Python绘制MySQL数据图实现数据可视化
2015/03/30 Python
Python求平面内点到直线距离的实现
2020/01/19 Python
Jupyter Notebook的连接密码 token查询方式
2020/04/21 Python
Python实现中英文全文搜索的示例
2020/12/04 Python
Python实现图片指定位置加图片水印(附Pyinstaller打包exe)
2021/03/04 Python
加拿大最大的书店:Indigo
2017/01/01 全球购物
什么是servlet链?
2014/07/13 面试题
师范生个人推荐信
2013/11/29 职场文书
经贸日语专业个人求职信范文
2014/04/29 职场文书
交通事故案件代理词
2015/05/23 职场文书
董事长开业致辞
2015/07/29 职场文书
业务员管理制度范本
2015/08/06 职场文书
2015年国庆放假通知范文
2015/08/18 职场文书
python函数的两种嵌套方法使用
2022/04/02 Python