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 两个窗体之间传值实现代码
Sep 25 Javascript
学习ExtJS(一) 之基础前提
Oct 07 Javascript
javascript学习基础笔记之DOM对象操作
Nov 03 Javascript
详解JavaScript的变量和数据类型
Nov 27 Javascript
JS实现本地存储信息的方法(基于localStorage与userData)
Feb 18 Javascript
Restify中接入Socket.io报Error:Can’t set headers的错误解决
Mar 28 Javascript
vue的传参方式汇总和router使用技巧
May 22 Javascript
微信小程序 JS动态修改样式的实现方法
Dec 16 Javascript
微信小程序列表时间戳转换实现过程解析
Oct 12 Javascript
解决三元运算符 报错“SyntaxError: can''t assign to conditional expression”
Feb 12 Javascript
Vue作用域插槽实现方法及作用详解
Jul 08 Javascript
vue Element-ui表格实现树形结构表格
Jun 07 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
实现树状结构的两种方法
2006/10/09 PHP
php array_search() 函数使用
2010/04/13 PHP
ThinkPHP缓存方法S()概述
2014/06/13 PHP
用PHP代替JS玩转DOM的思路及示例代码
2014/06/15 PHP
ThinkPHP实现将本地文件打包成zip下载
2014/06/26 PHP
thinkPHP实现瀑布流的方法
2014/11/29 PHP
PHP版本的选择5.2.17 5.3.27 5.3.28 5.4 5.5兼容性问题分析
2016/04/04 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
总结PHP中初始化空数组的最佳方法
2019/02/13 PHP
JavaScript DOM事件(笔记)
2015/04/08 Javascript
jQuery实现仿Google首页拖动效果的方法
2015/05/04 Javascript
jQuery结合CSS制作动态的下拉菜单
2015/10/27 Javascript
第一次接触神奇的Bootstrap导航条
2016/08/09 Javascript
js实现图片加载淡入淡出效果
2017/04/07 Javascript
完美解决axios跨域请求出错的问题
2018/02/05 Javascript
vue2.0 axios跨域并渲染的问题解决方法
2018/03/08 Javascript
angularjs下ng-repeat点击元素改变样式的实现方法
2018/09/12 Javascript
JavaScript实现页面中录音功能的方法
2019/06/04 Javascript
使用jQuery实现掷骰子游戏
2019/10/24 jQuery
[01:05:41]EG vs Optic Supermajor 败者组 BO3 第二场 6.6
2018/06/07 DOTA
跟老齐学Python之从if开始语句的征程
2014/09/14 Python
零基础写python爬虫之抓取百度贴吧并存储到本地txt文件改进版
2014/11/06 Python
用Python计算三角函数之acos()方法的使用
2015/05/15 Python
python字符串对其居中显示的方法
2015/07/11 Python
Python字典简介以及用法详解
2016/11/15 Python
python 多线程将大文件分开下载后在合并的实例
2018/11/09 Python
python之cv2与图像的载入、显示和保存实例
2018/12/05 Python
python浪漫表白源码
2019/04/05 Python
总结Python图形用户界面和游戏开发知识点
2019/05/22 Python
django将网络中的图片,保存成model中的ImageField的实例
2019/08/07 Python
详解pycharm连接远程linux服务器的虚拟环境的方法
2020/11/13 Python
html5 div布局与table布局详解
2016/11/16 HTML / CSS
18-35岁旅游团的全球领导者:Contiki
2017/02/08 全球购物
英国知名化妆品网站:Revolution Beauty(原TAM Beauty)
2018/02/28 全球购物
初中英语演讲稿
2014/04/29 职场文书
法院先进个人事迹材料
2014/05/04 职场文书