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效率个人经验谈(8-15更新),加入range技巧
Jan 09 Javascript
JS Array对象入门分析
Oct 30 Javascript
JavaScript 面向对象编程(1) 基础
May 18 Javascript
深入理解angularjs过滤器
May 25 Javascript
ES6深入理解之“let”能替代”var“吗?
Jun 28 Javascript
详解wow.js中各种特效对应的类名
Sep 13 Javascript
详解vue-cli与webpack结合如何处理静态资源
Sep 19 Javascript
vue中v-for加载本地静态图片方法
Mar 03 Javascript
vue 实现全选全不选的示例代码
Mar 29 Javascript
JavaScript动态生成表格的示例
Nov 02 Javascript
JS实现手风琴特效
Nov 08 Javascript
解决Vue大括号字符换行踩的坑
Nov 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
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
2017/02/04 PHP
layui数据表格自定义每页条数limit设置
2019/10/26 PHP
如何在PHP环境中使用ProtoBuf数据格式
2020/06/19 PHP
JS 建立对象的方法
2007/04/21 Javascript
ASP.NET jQuery 实例16 通过控件CustomValidator验证RadioButtonList
2012/02/03 Javascript
JavaScript 产生不重复的随机数三种实现思路
2012/12/13 Javascript
jquery $.each 和for怎么跳出循环终止本次循环
2013/09/27 Javascript
javascript相等运算符与等同运算符详细介绍
2013/11/09 Javascript
JavaScript实现数字数组按照倒序排列的方法
2015/04/06 Javascript
JavaScript数组复制详解
2017/02/02 Javascript
JavaScript正则表达式校验与递归函数实际应用实例解析
2017/08/04 Javascript
Angular5中调用第三方js插件的方法
2018/02/26 Javascript
《javascript少儿编程》location术语总结
2018/05/27 Javascript
深入浅析AngularJs模版与v-bind
2018/07/06 Javascript
Vue-router 切换组件页面时进入进出动画方法
2018/09/01 Javascript
Vue使用NPM方式搭建项目
2018/10/25 Javascript
js+html实现周岁年龄计算器
2019/06/25 Javascript
Vue全局使用less样式,组件使用全局样式文件中定义的变量操作
2020/10/21 Javascript
JavaScript快速调试的两个技巧
2020/11/04 Javascript
spyder常用快捷键(分享)
2017/07/19 Python
WIn10+Anaconda环境下安装PyTorch(避坑指南)
2019/01/30 Python
ubuntu 安装pyqt5和卸载pyQt5的方法
2020/03/24 Python
python利用google翻译方法实例(翻译字幕文件)
2020/09/21 Python
日本面向世界,国际级的免税在线购物商城:DOKODEMO
2017/02/01 全球购物
精油和天然健康美容产品:Art Naturals
2018/01/27 全球购物
Becextech新西兰:数码单反相机和手机在线商店
2018/04/27 全球购物
欧洲、亚洲、非洲和拉丁美洲的度假套餐:Great Value Vacations
2019/03/30 全球购物
经典婚礼主持词
2014/03/13 职场文书
股权收购意向书
2014/04/01 职场文书
《最大的麦穗》教学反思
2014/04/17 职场文书
亮剑观后感
2015/06/05 职场文书
保姆聘用合同
2015/09/21 职场文书
2016年度创先争优活动总结
2016/04/05 职场文书
详解Vue的列表渲染
2021/11/20 Vue.js
MySQL数据库查询进阶之多表查询详解
2022/04/08 MySQL
Python中的matplotlib绘制百分比堆叠柱状图,并为每一个类别设置不同的填充图案
2022/04/20 Python