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 相关文章推荐
小议Function.apply() 之一------(函数的劫持与对象的复制)
Nov 30 Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
Oct 20 Javascript
Firefox中autocomplete="off" 设置不起作用Bug的解决方法
Mar 25 Javascript
js 控制页面跳转的5种方法
Sep 09 Javascript
jquery 设置style:display的方法
Jan 29 Javascript
使用window.prompt()实现弹出用户输入的对话框
Apr 13 Javascript
移动Web中图片自适应的两种JavaScript解决方法
Jun 18 Javascript
js实现音乐播放控制条
Sep 09 Javascript
javascript 开发之网页兼容各种浏览器
Sep 28 Javascript
对angularjs框架下controller间的传值方法详解
Oct 08 Javascript
vue 导航内容设置选中状态样式的例子
Nov 01 Javascript
使用node.JS中的url模块解析URL信息
Feb 06 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
兼容firefox,chrome的网页灰度效果
2011/08/08 PHP
php发送与接收流文件的方法
2015/02/11 PHP
PHP将Excel导入数据库及数据库数据导出至Excel的方法
2015/06/24 PHP
YII框架页面缓存操作示例
2019/04/29 PHP
Javascript中获取出错代码所在文件及行数的代码
2010/09/23 Javascript
js自动闭合html标签(自动补全html标记)
2012/10/04 Javascript
ko knockoutjs动态属性绑定技巧应用
2012/11/14 Javascript
js取得url地址参数实例
2013/02/22 Javascript
利用Jquery实现可多选的下拉框
2014/02/21 Javascript
JavaScript中自定义事件用法分析
2014/12/23 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
用户代理字符串userAgent可实现的四个识别
2015/09/20 Javascript
学习Javascript面向对象编程之封装
2016/02/23 Javascript
JavaScript添加随滚动条滚动窗体的方法
2016/02/23 Javascript
jquery ztree实现模糊搜索功能
2016/02/25 Javascript
Angularjs过滤器使用详解
2016/05/25 Javascript
js实现随机点名系统(实例讲解)
2017/10/18 Javascript
js Array.slice的8种不同用法示例
2019/07/10 Javascript
vue多个元素的样式选择器问题
2019/11/29 Javascript
js实现随机点名器精简版
2020/06/29 Javascript
Python基于select实现的socket服务器
2016/04/13 Python
python扫描proxy并获取可用代理ip的实例
2017/08/07 Python
python中使用print输出中文的方法
2018/07/16 Python
kafka-python批量发送数据的实例
2018/12/27 Python
python-itchat 统计微信群、好友数量,及原始消息数据的实例
2019/02/21 Python
pyqt5 tablewidget 利用线程动态刷新数据的方法
2019/06/17 Python
python itsdangerous模块的具体使用方法
2020/02/17 Python
Python web如何在IIS发布应用过程解析
2020/05/27 Python
纽约市的奢华内衣目的地:Anya Lust
2019/08/02 全球购物
泰国国际航空公司官网:Thai Airways International
2019/12/04 全球购物
巡警年度自我鉴定
2014/02/21 职场文书
元旦晚会活动总结
2014/07/09 职场文书
土地租赁意向书
2014/07/30 职场文书
vue2实现provide inject传递响应式
2021/05/21 Vue.js
python 远程执行命令的详细代码
2022/02/15 Python
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python