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 相关文章推荐
JS中的数组的sort方法使用示例
Jan 22 Javascript
jquery重复提交请求的原因浅析
May 23 Javascript
javascript常用函数归纳整理
Oct 31 Javascript
JavaScript改变CSS样式的方法汇总
May 07 Javascript
微信小程序-拍照或选择图片并上传文件
Jan 06 Javascript
JavaScript错误处理和堆栈追踪详解
Apr 18 Javascript
运用jQuery写的验证表单(实例讲解)
Jul 06 jQuery
动手写一个angular版本的Message组件的方法
Dec 16 Javascript
elementUI多选框反选的实现代码
Apr 03 Javascript
一篇文章弄懂javascript中的执行栈与执行上下文
Aug 09 Javascript
使用VScode 插件debugger for chrome 调试react源码的方法
Sep 13 Javascript
vue 项目引入echarts 添加点击事件操作
Sep 09 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
从C/C++迁移到PHP——判断字符类型的函数
2006/10/09 PHP
PHP file_get_contents 函数超时的几种解决方法
2009/07/30 PHP
PHP和javascript常用正则表达式及用法实例
2014/07/01 PHP
php简单计算页面加载时间的方法
2015/06/19 PHP
分享php多功能图片处理类
2016/05/15 PHP
php封装的smarty类完整实例
2016/10/19 PHP
Javascript+XMLHttpRequest+asp.net无刷新读取数据库数据
2009/08/09 Javascript
javascript开发随笔二 动态加载js和文件
2011/11/25 Javascript
利用jquery的获取JS文件中的字符串内容
2012/02/14 Javascript
jQuery实现的超酷苹果风格图标滑出菜单效果代码
2015/09/16 Javascript
JS针对Array的各种操作汇总
2016/11/29 Javascript
从零开始学习Node.js系列教程一:http get和post用法分析
2017/04/13 Javascript
vue-cli webpack 引入jquery的方法
2018/01/10 jQuery
详解js的视频和音频采集
2018/08/09 Javascript
解决select2在bootstrap modal中不能正常使用的问题
2018/08/09 Javascript
微信小程序数据分析之自定义分析的实现
2018/08/17 Javascript
vue打包之后生成一个配置文件修改接口的方法
2018/12/09 Javascript
vue添加自定义右键菜单的完整实例
2020/12/08 Vue.js
[45:06]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第二场 11.28
2020/12/02 DOTA
python函数装饰器用法实例详解
2015/06/04 Python
python字典的常用操作方法小结
2016/05/16 Python
Python实现全排列的打印
2018/08/18 Python
Python3+Pycharm+PyQt5环境搭建步骤图文详解
2019/05/29 Python
树莓派极简安装OpenCv的方法步骤
2019/10/10 Python
pytorch实现特殊的Module--Sqeuential三种写法
2020/01/15 Python
django模板获取list中指定索引的值方式
2020/05/14 Python
利用Python实现Excel的文件间的数据匹配功能
2020/06/16 Python
分享一枚pycharm激活码适用所有pycharm版本我的pycharm2020.2.3激活成功
2020/11/20 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
使用HTML5 Geolocation实现一个距离追踪器
2018/04/09 HTML / CSS
Oracle性能调优原则
2012/05/03 面试题
医学毕业生自荐信
2013/10/11 职场文书
机修工工作职责
2014/02/21 职场文书
现金出纳岗位职责
2014/03/15 职场文书
劳模事迹材料范文
2014/12/24 职场文书
Python绘制地图神器folium的新人入门指南
2021/05/23 Python