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 写的简单进度条控件
Jan 22 Javascript
利用JS重写Cognos右键菜单的实现代码
Apr 11 Javascript
jQuery表单域属性过滤器用法分析
Feb 10 Javascript
Jquery和angularjs获取check框选中的值的方法汇总
Jan 17 Javascript
让html元素随浏览器的大小自适应垂直居中的实现方法
Oct 12 Javascript
MUI 上拉刷新/下拉加载功能实例代码
Apr 13 Javascript
详解webpack进阶之插件篇
Jul 06 Javascript
AngularJS发送异步Get/Post请求方法
Aug 13 Javascript
jquery实现下载图片功能
Jul 18 jQuery
Webpack按需加载打包chunk命名的方法
Sep 22 Javascript
微信小程序实现分页加载效果
Nov 19 Javascript
vite+vue3.0+ts+element-plus快速搭建项目的实现
Jun 24 Vue.js
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漏洞之跨网站请求伪造与防止伪造方法
2013/08/15 PHP
php批量删除cookie的简单实现方法
2015/01/26 PHP
php中header跳转使用include包含解决参数丢失问题
2015/05/08 PHP
php进行ip地址掩码运算处理的方法
2016/07/11 PHP
使用laravel和ajax实现整个页面无刷新的操作方法
2019/10/03 PHP
javascript 获取url参数和script标签中获取url参数函数代码
2010/01/22 Javascript
腾讯与新浪的通过IP地址获取当前地理位置(省份)的接口
2010/07/26 Javascript
THREE.JS入门教程(2)着色器-上
2013/01/24 Javascript
我的Node.js学习之路(二)NPM模块管理
2014/07/06 Javascript
javascript函数式编程实例分析
2015/04/25 Javascript
JavaScript检测鼠标移动方向的方法
2015/05/22 Javascript
利用jquery实现验证输入的是否是数字、小数,包含保留几位小数
2016/12/07 Javascript
Vue.js基础学习之class与样式绑定
2017/03/20 Javascript
vue实现前进刷新后退不刷新效果
2018/01/26 Javascript
详解js跨域请求的两种方式,支持post请求
2018/05/05 Javascript
微信小程序实现tab页面切换功能
2018/07/13 Javascript
mpvue 如何使用腾讯视频插件的方法
2018/07/16 Javascript
vue element upload组件 file-list的动态绑定实现
2019/10/11 Javascript
Layui实现数据表格默认全部显示(不要分页)
2019/10/26 Javascript
vue组件创建的三种方式小结
2020/02/03 Javascript
pyramid配置session的方法教程
2013/11/27 Python
Python+MongoDB自增键值的简单实现
2016/11/04 Python
python石头剪刀布小游戏(三局两胜制)
2021/01/20 Python
python 实现在tkinter中动态显示label图片的方法
2019/06/13 Python
如何使用Python标准库进行性能测试
2019/06/25 Python
Python如何计算语句执行时间
2019/11/22 Python
Python用K-means聚类算法进行客户分群的实现
2020/08/23 Python
介绍一下代理模式(Proxy)
2014/10/17 面试题
自我鉴定四大框架
2014/01/17 职场文书
写给老师的表扬信
2014/01/21 职场文书
特色冷饮店创业计划书
2014/01/28 职场文书
群众路线专项整治工作情况报告
2014/10/28 职场文书
兴趣班停课通知
2015/04/24 职场文书
中学社团活动总结
2015/05/07 职场文书
运动会宣传稿50字
2015/07/23 职场文书
python之np.argmax()及对axis=0或者1的理解
2021/06/02 Python