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插件开发之图片放大镜效果(仿淘宝)
Nov 19 Javascript
jquery鼠标滑过提示title具体实现代码
Aug 06 Javascript
利用js读取动态网站从服务器端返回的数据
Feb 10 Javascript
防止登录页面出现在frame中js代码
Jul 22 Javascript
Javascript让DEDECMS告别手写Tag
Sep 01 Javascript
Javascript设计模式之观察者模式的多个实现版本实例
Mar 03 Javascript
基于OL2实现百度地图ABCD marker的效果
Oct 01 Javascript
详解angular2采用自定义指令(Directive)方式加载jquery插件
Feb 09 Javascript
seajs中模块依赖的加载处理实例分析
Oct 10 Javascript
JavaScript基于面向对象实现的猜拳游戏
Jan 03 Javascript
socket在egg中的使用实例代码详解
May 30 Javascript
浅谈vue.watch的触发条件是什么
Nov 07 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编写daemon process详解及实例代码
2016/09/30 PHP
thinkPHP框架实现多表查询的方法
2018/06/14 PHP
JS性能优化笔记搜索整理
2013/08/21 Javascript
NodeJS的url截取模块url-extract的使用实例
2013/11/18 NodeJs
jQuery动态星级评分效果实现方法
2015/08/06 Javascript
JavaScript处理解析JSON数据过程详解
2015/09/11 Javascript
jQuery实现模仿微博下拉滚动条加载数据效果
2015/12/25 Javascript
深入学习js瀑布流布局
2016/10/14 Javascript
原生js实现简单的Ripple按钮实例代码
2017/03/24 Javascript
解决Layui数据表格中checkbox位置不居中的方法
2018/08/15 Javascript
新手入门带你学习JavaScript引擎运行原理
2019/06/24 Javascript
JavaScript使用canvas绘制随机验证码
2020/02/17 Javascript
[39:53]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第一场 11.19
2020/11/19 DOTA
Python迭代用法实例教程
2014/09/08 Python
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
python的dataframe转换为多维矩阵的方法
2018/04/11 Python
python3 实现验证码图片切割的方法
2018/12/07 Python
python使用参数对嵌套字典进行取值的方法
2019/04/26 Python
python自动结束mysql慢查询会话的实例代码
2019/10/27 Python
python爬虫模拟浏览器的两种方法实例分析
2019/12/09 Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
2020/03/02 Python
东南亚旅游平台:The Trip Guru
2018/01/01 全球购物
四川internet信息高速公路(C#)笔试题
2012/02/29 面试题
食品厂厂长岗位职责
2014/01/30 职场文书
《藤野先生》教学反思
2014/02/19 职场文书
校外活动方案
2014/08/28 职场文书
上课迟到检讨书300字
2014/10/15 职场文书
2014年秘书工作总结
2014/11/25 职场文书
事业单位工作人员年度考核个人总结
2015/02/12 职场文书
开展警示教育活动总结
2015/05/09 职场文书
九不准学习心得体会
2016/01/23 职场文书
话题作文之学会尊重
2019/12/16 职场文书
这样写python注释让代码更加的优雅
2021/06/02 Python
如何打开Win11系统注册表编辑器?Win11注册表编辑器打开修复方法
2022/04/05 数码科技
Docker部署Mysql8的实现步骤
2022/07/07 Servers
在SQL Server中使用 Try Catch 处理异常的示例详解
2022/07/15 SQL Server