浮点数的比较

371 阅读2分钟

前些天刷题的时候,碰到了关于浮点数比较的一些细节问题,所以我重温了一下算法笔记中的相关介绍(2.9.2节有兴趣的同学可以自己去看一下这本书),借此写下了这篇博客

浮点数的比较

由于计算机中采用有限位的二进制编码,因此浮点数在计算机中的存储并不总是精确的。例如:在经过大量计算后,一个浮点型的数3.14在计算机中就可能存储成3.140000000.1,或者3.1399999999,等等,这种情况下会对比较操作造成极大的干扰,== 就不对了(在C/C++中“==”要完全相同才是true)。所以我们需要引入一个极小的数eps来对这种误差进行修正。

1. 等于(==)

在这里插入图片描述 等于区间示意图

只要a落在了[b-eps, b+eps]这个区间之间,就可以判断a与b相等(即a==b成立);
根据经验,eps取10^-8是一个合适的数字,对于大多数情况既不会漏判也不会误判;
cosnt double eps = 1e-8;
  • 用宏定义来写比较操作
#define Equ(a, b) ((fabs((a)-(b))) < (eps))
  • 如上,将a与b相减,若差的绝对值小于极小量eps,则返回true;
  • 加上这么多的括号,是为了防止宏定义可能带来的错误;
  • 想使用不等于,直接在Equ函数前加一个! 即可;

2. 大于(>)

大于区间示意图

如果a要大于b,那么就必须在误差eps的波动范围之外大于b,因此只有大于b+eps的数才能判定为
大于b(即a减b大于eps)
  • 用宏定义来写大于函数如下:
#define More(a, b) (((a)-(b)) > (eps))

3. 小于(<)

在这里插入图片描述 小于区间示意图

如果a要小于b,那么就必须在误差eps的波动范围之外小于b,即只有小于b-eps的数才可以判定为
小于b(即a减b小于-eps)
  • 用宏定义描述函数如下:
#define Less(a, b) (((a) - (b)) < (-eps))

4. 大于等于(>=)

在这里插入图片描述 大于等于区间示意图

可以将大于等于运算符,理解为大于和等于的结合,所以要判定a大于等于b,就要让a在误差波动范
围内能判定其大于或者等于b,即大于b-eps的数都可以判定为大于等于b
  • 用宏定义表示函数如下:
#define MoreEqu(a, b) (((a) - (b)) > (-eps))

5. 小于等于(<=)

在这里插入图片描述 小于等于区间示意图

与大于等于同理,考虑误差波动范围,小于b + eps的数都可以判定为小于等于b
  • 用宏定义表示函数如下:
#define LessEqu(a, b) (((a) - (b)) < (eps))

6. 附加一个圆周率π

const double Pi = acos(-1.0); // 因为cos(π) = -1;
  • 坑:还有一些细节,后续会再补充