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 相关文章推荐
vuejs响应用户事件(如点击事件)
Mar 14 Javascript
jquery replace方法去空格
May 08 jQuery
微信小程序 页面跳转事件绑定的实例详解
Sep 20 Javascript
AngularJs 禁止模板缓存的方法
Nov 28 Javascript
详解使用VueJS开发项目中的兼容问题
Aug 02 Javascript
实例分析vue循环列表动态数据的处理方法
Sep 28 Javascript
vue如何根据网站路由判断页面主题色详解
Nov 02 Javascript
js操作table中tr的顺序实现上移下移一行的效果
Nov 22 Javascript
js实现的在本地预览图片功能示例
Nov 09 Javascript
简介JavaScript错误处理机制
Aug 04 Javascript
基于JavaScript实现简单的轮播图
Mar 03 Javascript
canvas实现贪食蛇的实践
Feb 15 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中ob(Output Buffer 输出缓冲)函数使用方法
2007/07/21 PHP
php array_intersect()函数使用代码
2009/01/14 PHP
php 解压rar文件及zip文件的方法
2014/05/05 PHP
stripos函数知识点实例分享
2019/02/11 PHP
Dom在ajax技术中的作用说明
2010/10/25 Javascript
SwfUpload在IE10上不出现上传按钮的解决方法
2013/06/25 Javascript
在javascript中实现函数数组的方法
2013/12/25 Javascript
jquery控制select的text/value值为选中状态
2014/06/03 Javascript
Bootstrap所支持的表单控件实例详解
2016/05/16 Javascript
js编写一个简单的产品放大效果代码
2016/06/27 Javascript
Bootstrap风格的WPF样式
2016/12/07 Javascript
详解Vue自定义过滤器的实现
2017/01/10 Javascript
Vue系列:通过vue-router如何传递参数示例
2017/01/16 Javascript
Angular2下使用pdf插件的方法详解
2017/04/29 Javascript
详解vue.js之绑定class和style的示例代码
2017/08/24 Javascript
element UI upload组件上传附件格式限制方法
2018/09/04 Javascript
一步一步的了解webpack4的splitChunk插件(小结)
2018/09/17 Javascript
详解vue在项目中使用百度地图
2019/03/26 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&平移轮播效果
2019/08/16 Javascript
使用Vue.set()方法实现响应式修改数组数据步骤
2019/11/09 Javascript
[49:13]DOTA2上海特级锦标赛C组资格赛#1 OG VS LGD第一局
2016/02/27 DOTA
[06:43]2018DOTA2国际邀请赛寻真——VGJ.Thunder
2018/08/11 DOTA
python实现文件分组复制到不同目录的例子
2014/06/04 Python
python+pandas生成指定日期和重采样的方法
2018/04/11 Python
对python中的高效迭代器函数详解
2018/10/18 Python
Python 动态变量名定义与调用方法
2020/02/09 Python
python 回溯法模板详解
2020/02/26 Python
详解Python中import机制
2020/09/11 Python
Numpy中np.max的用法及np.maximum区别
2020/11/27 Python
统计员岗位职责
2013/11/14 职场文书
护士自我评价
2014/02/01 职场文书
爱情保证书大全
2014/04/29 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
2014教师研修学习体会
2014/07/08 职场文书
班委竞选稿范文
2015/11/21 职场文书
如何解决goland,idea全局搜索快捷键失效问题
2022/04/03 Golang