Javascript 浮点运算精度问题分析与解决


Posted in Javascript onMarch 26, 2014

分析

JavaScript 只有一种数字类型 Number ,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的。 浮点数的精度问题不是JavaScript特有的,因为有些小数以二进制表示位数是无穷的:

十进制           二进制
0.1              0.0001 1001 1001 1001 ...
0.2              0.0011 0011 0011 0011 ...
0.3              0.0100 1100 1100 1100 ...
0.4              0.0110 0110 0110 0110 ...
0.5              0.1
0.6              0.1001 1001 1001 1001 ...

所以比如 1.1 ,其程序实际上无法真正的表示 ‘1.1',而只能做到一定程度上的准确,这是无法避免的精度丢失:

1.09999999999999999

在JavaScript中问题还要复杂些,这里只给一些在Chrome中测试数据:

 输入               输出
1.0-0.9 == 0.1     False
1.0-0.8 == 0.2     False
1.0-0.7 == 0.3     False
1.0-0.6 == 0.4     True
1.0-0.5 == 0.5     True
1.0-0.4 == 0.6     True
1.0-0.3 == 0.7     True
1.0-0.2 == 0.8     True
1.0-0.1 == 0.9     True

解决

那如何来避免这类 1.0-0.9 != 0.1 的非bug型问题发生呢?下面给出一种目前用的比较多的解决方案, 在判断浮点运算结果前对计算结果进行精度缩小,因为在精度缩小的过程总会自动四舍五入:

(1.0-0.9).toFixed(digits)                   // toFixed() 精度参数须在 0 与20 之间
parseFloat((1.0-0.9).toFixed(10)) === 0.1   // 结果为True
parseFloat((1.0-0.8).toFixed(10)) === 0.2   // 结果为True
parseFloat((1.0-0.7).toFixed(10)) === 0.3   // 结果为True
parseFloat((11.0-11.8).toFixed(10)) === -0.8   // 结果为True

方法提炼
// 通过isEqual工具方法判断数值是否相等
function isEqual(number1, number2, digits){
 digits = digits == undefined? 10: digits; // 默认精度为10
 return number1.toFixed(digits) === number2.toFixed(digits);
}
isEqual(1.0-0.7, 0.3);  // return true
// 原生扩展方式,更喜欢面向对象的风格
Number.prototype.isEqual = function(number, digits){
 digits = digits == undefined? 10: digits; // 默认精度为10
 return this.toFixed(digits) === number.toFixed(digits);
}
(1.0-0.7).isEqual(0.3); // return true
Javascript 相关文章推荐
JavaScript实现快速排序(自已编写)
Dec 19 Javascript
JQuery中阻止事件冒泡几种方式及其区别介绍
Jan 15 Javascript
js获取 type=radio 值的方法
May 09 Javascript
JQUERY实现网页右下角固定位置展开关闭特效的方法
Jul 27 Javascript
解决angular的post请求后SpringMVC后台接收不到参数值问题的方法
Dec 10 Javascript
node.js中 stream使用教程
Aug 28 Javascript
JavaScript 中 avalon绑定属性总结
Oct 19 Javascript
Bootstrap BootstrapDialog使用详解
Feb 17 Javascript
BootStrap表单时间选择器详解
May 09 Javascript
jQuery实现表单动态添加数据并提交的方法
Jul 19 jQuery
解决Layui 表单提交数据为空的问题
Aug 15 Javascript
vue实现全屏滚动效果(非fullpage.js)
Mar 07 Javascript
javascript 3d 逐侦产品展示(核心精简)
Mar 26 #Javascript
Node.js模拟浏览器文件上传示例
Mar 26 #Javascript
JavaScript关闭当前页面(窗口)不带任何提示
Mar 26 #Javascript
JavaScript数字和字符串转换示例
Mar 26 #Javascript
jquery实现瀑布流效果分享
Mar 26 #Javascript
jquery实现效果比较好的table选中行颜色
Mar 25 #Javascript
Jquery对数组的操作技巧整理
Mar 25 #Javascript
You might like
PHP更新购物车数量(表单部分/PHP处理部分)
2013/05/03 PHP
PHP中copy on write写时复制机制介绍
2014/05/13 PHP
php与flash as3 socket通信传送文件实现代码
2014/08/16 PHP
PHP图像处理之imagecreate、imagedestroy函数介绍
2014/11/19 PHP
既简单又安全的PHP验证码 附调用方法
2016/06/02 PHP
php版微信开发Token验证失败或请求URL超时问题的解决方法
2016/09/23 PHP
实例讲解YII2中多表关联的使用方法
2017/07/21 PHP
使用PHPStorm+XDebug搭建单步调试环境
2017/11/19 PHP
PHP Include文件实例讲解
2019/02/15 PHP
Laravel5.1 框架表单验证操作实例详解
2020/01/07 PHP
Ext JS Grid在IE6 下宽度的问题解决方法
2009/02/15 Javascript
jquery autocomplete自动完成插件的的使用方法
2010/08/07 Javascript
addEventListener 的用法示例介绍
2014/05/07 Javascript
js实现微信分享代码
2020/10/11 Javascript
防止Node.js中错误导致进程阻塞的办法
2016/08/11 Javascript
关于Javascript回调函数的一个妙用
2016/08/29 Javascript
详解利用exif.js解决ios手机上传竖拍照片旋转90度问题
2016/11/04 Javascript
详解基于vue-cli配置移动端自适应
2018/01/13 Javascript
Node.JS在命令行中检查Chrome浏览器是否安装并打开指定网址
2019/05/21 Javascript
原生JS实现九宫格抽奖
2020/09/13 Javascript
[48:44]2014 DOTA2国际邀请赛中国区预选赛5.21 TongFu VS HGT
2014/05/22 DOTA
Python 可爱的大小写
2008/09/06 Python
Python切片知识解析
2016/03/06 Python
tensorflow实现简单的卷积神经网络
2018/05/24 Python
python GUI计算器的实现
2020/10/09 Python
Python 数据分析之逐块读取文本的实现
2020/12/14 Python
请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1
2015/07/16 面试题
计算机应用专业学生的自我评价分享
2013/11/03 职场文书
学校三八妇女节活动情况总结
2014/03/09 职场文书
大学生就业意向书范文
2014/04/01 职场文书
商业街策划方案
2014/05/31 职场文书
2014年预备党员群众路线教育实践活动对照检查材料思想汇报
2014/10/02 职场文书
2014年团支部工作总结
2014/11/17 职场文书
2015年学校总务处工作总结
2015/05/19 职场文书
情况说明书怎么写
2015/10/08 职场文书
教师廉政准则心得体会
2016/01/20 职场文书