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 相关文章推荐
Mootools 1.2教程(2) DOM选择器
Sep 14 Javascript
JavaScript继承方式实例
Oct 29 Javascript
判断是否安装flash player及当前版本的JS代码
Aug 08 Javascript
jquery实现表格中点击相应行变色功能效果【实例代码】
May 09 Javascript
JavaScript新增样式规则(推荐)
Jul 19 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
Nov 12 Javascript
基于打包工具Webpack进行项目开发实例
May 29 Javascript
从理论角度讨论JavaScript闭包
Apr 03 Javascript
基于ssm框架实现layui分页效果
Jul 27 Javascript
jQuery pager.js 插件动态分页功能实例分析
Aug 02 jQuery
VsCode与Node.js知识点详解
Sep 05 Javascript
JS数组方法reverse()用法实例分析
Jan 18 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变量引用的面试题
2010/08/08 PHP
深入php中var_dump方法的使用详解
2013/06/24 PHP
php解决约瑟夫环算法实例分析
2019/09/30 PHP
调试php程序的简单步骤
2019/10/04 PHP
jQuery EasyUI 的EasyLoader功能介绍
2010/09/12 Javascript
理解Javascript_10_对象模型
2010/10/16 Javascript
JS中动态添加事件(绑定事件)的代码
2011/01/09 Javascript
from 表单提交返回值用post或者是get方法实现
2013/08/21 Javascript
JS:window.onload的使用介绍
2013/11/13 Javascript
浅析Node.js中的内存泄漏问题
2015/06/23 Javascript
简单实现js间歇或无缝滚动效果
2016/06/29 Javascript
基于javascript实现数字英文验证码
2017/01/25 Javascript
jQuery代码实现实时获取时间
2017/01/29 Javascript
深入理解Angular4中的依赖注入
2017/06/07 Javascript
Vue列表页渲染优化详解
2017/07/24 Javascript
温故知新——JavaScript中的字符串连接问题最全总结(推荐)
2017/08/21 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
vue cli3 配置proxy代理无效的解决
2019/10/30 Javascript
解决vue 子组件修改父组件传来的props值报错问题
2019/11/09 Javascript
js观察者模式的弹幕案例
2020/11/23 Javascript
浅谈Vue使用Elementui修改默认的最快方法
2020/12/05 Vue.js
[01:06]DOTA2小知识课堂 Ep.02 吹风竟可解梦境缠绕
2019/12/05 DOTA
Python处理RSS、ATOM模块FEEDPARSER介绍
2015/02/18 Python
python统计文本文件内单词数量的方法
2015/05/30 Python
Puppeteer使用示例详解
2019/06/20 Python
浅谈PyTorch的可重复性问题(如何使实验结果可复现)
2020/02/20 Python
django实现日志按日期分割
2020/05/21 Python
CSS3实现跳动的动画效果
2016/09/12 HTML / CSS
AE美国鹰美国官方网站:American Eagle Outfitters
2016/08/22 全球购物
员工培训心得体会
2013/12/30 职场文书
升国旗演讲稿
2014/09/05 职场文书
防灾减灾宣传标语
2014/10/07 职场文书
2016年中秋祝酒词
2015/11/26 职场文书
python munch库的使用解析
2021/05/25 Python
使用Navicat Premium工具将oracle数据库迁移到MySQL
2021/05/27 Oracle
golang特有程序结构入门教程
2021/06/02 Python