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中实现命名空间
Nov 23 Javascript
Extjs 几个方法的讨论
Jan 28 Javascript
JavaScript 类似flash效果的立体图片浏览器
Feb 08 Javascript
Javascript延迟执行实现方法(setTimeout)
Dec 30 Javascript
jquery延迟加载外部js实现代码
Jan 11 Javascript
jquery中.add()的使用分析
Apr 26 Javascript
javascript中hasOwnProperty() 方法使用指南
Mar 09 Javascript
JS实现网页游戏中滑块响应鼠标点击移动效果
Oct 19 Javascript
多种js图片预加载实现方式分享
Feb 19 Javascript
浅谈目前可以使用ES10的5个新特性
Jun 25 Javascript
浅谈vue中组件绑定事件时是否加.native
Nov 09 Javascript
Vue中常用rules校验规则(实例代码)
Nov 14 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
使用XDebug调试及单元测试覆盖率分析
2011/01/27 PHP
nginx下安装php7+php5
2016/07/31 PHP
tp5框架使用composer实现日志记录功能示例
2019/01/10 PHP
JS IE和FF兼容性问题汇总
2009/02/09 Javascript
jquery ajax提交表单数据的两种实现方法
2010/04/29 Javascript
超级有用的13个基于jQuery的内容滚动插件和教程
2011/07/31 Javascript
Javascript根据指定下标或对象删除数组元素
2012/12/21 Javascript
jquery动态添加删除div 具体实现
2013/07/20 Javascript
jQuery设置与获取HTML,文本和值的简单实例
2014/02/26 Javascript
jQuery中事件对象e的事件冒泡用法示例介绍
2014/04/25 Javascript
JavaScript将当前时间转换成UTC标准时间的方法
2015/04/06 Javascript
jQuery中closest和parents的区别分析
2015/05/07 Javascript
javascript的列表切换【实现代码】
2016/05/03 Javascript
javascript中数组和字符串的方法对比
2016/07/20 Javascript
Vuejs第九篇之组件作用域及props数据传递实例详解
2016/09/05 Javascript
xmlplus组件设计系列之分隔框(DividedBox)(8)
2017/05/02 Javascript
原生JS实现不断变化的标签
2017/05/22 Javascript
原生js无缝轮播插件使用详解
2020/03/09 Javascript
[01:01:14]完美世界DOTA2联赛PWL S2 SZ vs Rebirth 第一场 11.21
2020/11/23 DOTA
python实现人人网登录示例分享
2014/01/19 Python
Python新手入门最容易犯的错误总结
2017/04/24 Python
python中关于for循环的碎碎念
2017/06/30 Python
Python内置模块hashlib、hmac与uuid用法分析
2018/02/12 Python
python2.7+selenium2实现淘宝滑块自动认证功能
2018/02/24 Python
python简单验证码识别的实现方法
2019/05/10 Python
python 搜索大文件的实例代码
2019/07/08 Python
python文字转语音的实例代码分析
2019/11/12 Python
基于django micro搭建网站实现加水印功能
2020/05/22 Python
CSS3 完美实现圆角效果
2009/07/13 HTML / CSS
什么是.net的Remoting技术
2016/07/08 面试题
Linux管理员面试经常问道的相关命令
2014/12/12 面试题
信息与计算机科学职业规划范文:成为一艘有方向的船
2014/09/11 职场文书
2014年营业员工作总结
2014/11/18 职场文书
2014年合同管理工作总结
2014/12/02 职场文书
焦裕禄纪念馆观后感
2015/06/09 职场文书
python对文档中元素删除,替换操作
2022/04/02 Python