C++ 浮点数精度判定

点击蓝字

ce2dc9d13de46f5d3bcd49eee867c3ee.png

关注我们

来源于网络,侵删

一、引例

看下下面这段代码,会输出什么结果呢?

double x = 0;
  for (int i = 0; i < 10; ++i) {
    x += 0.1;
  }
  printf("%d\n", x == 1);

输出如下:

0

引起这种反差的原因就是浮点误差,浮点数在存储的时候是有精度误差的,所以进行浮点数等于判定的时候不能用 ‘==’,那么接下来我们看下浮点数的表示;

二、浮点数表示

1、IEEE 754

IEEE二进制浮点数算术标准(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零 -0)与反常值),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”。

基于这个规定,任何浮点数都可以表示成如下形式:

41f317e9e8e3c34d4a390d02c99daf93.png

d7edb90421a124c706370f19c62bae67.png

2、单精度和双精度

  • C++ 中两种浮点数,float 和 double,分别代表单精度和双精度;

  • 单精度尾数占23个比特位,指数占8个比特位;双精度尾数占52个比特位,指数占11个比特位;

  • 由于结构相同,这里只介绍单精度浮点数;

3、单精度浮点数表示法

  • 如图为 32位 的浮点数的二进制表示,总共 32 个比特位(取值 0 或 1);

bc385e9d8585123813419a321501b40f.png

  • S 在最高位,代表符号,负数为1,正数为0;

  • E 为从高到低的第 30 - 23 位,总共 8 位,代表指数偏移,存储的是加上了 127 以后的值(原因是指数有可能是负数);

  • F 代表二进制科学计数法的尾数,总共 23 位,因为是科学计数法,所以开头一定是 “1.” 开头,所以尾数有效位数为 24 位;

4、举例说明

【示例】 对于−18.375这个浮点数,求出它的二进制存储格式;

341c96504e932295d3a7930e94eb16b1.png

2871a2aa424631afcaec1fc9281b1e1a.png

5、代码测试

C/C++ 中可以用如下代码对浮点数取地址转换成整型后输出整数的二进制表示;

float a = -18.375;
  unsigned int v = *((unsigned int *)&a);

三、浮点数判定

1、精度定义

5fdc7b9304e76b9874d3cd2295f78d9f.png

#define eps 1e-6

2、相等判定

介于浮点数的表示方式,不能用 ‘==’ 进行相等判定,必须将两数相减,取绝对值以后,根据结果是否小于某个精度来判定两者是否相等;

bool EQ(double a, double b) {   // EQual
  return fabs(a - b) < eps;
}

3、不相等判定

‘不相等’ 就是 ‘相等’ 的 ‘非’(取反);

bool NEQ(double a, double b) {  // NotEQual
  return !EQ(a, b);
}

4、大于等于判定

‘大于等于’ 就是 ‘大于 或 等于’ 的意思,需要拆分成如下形式:

bool GET(double a, double b) {    // GreaterEqualThan
  return a > b || EQ(a, b);
}

5、小于等于判定

‘小于等于’ 就是 ‘小于 或 等于’ 的意思,需要拆分成如下形式:

bool SET(double a, double b) {   // SmallerEqualThan
  return a < b || EQ(a, b);
}

6、小于判定

‘小于’ 就是 ‘大于等于’ 的 ‘非’,需要拆分成如下形式:

注意:千万不能直接用 a < b

bool ST(double a, double b) {   // SmallerThan
  return a < b && NEQ(a, b);
}

7、大于判定

‘大于’ 就是 ‘小于等于’ 的 ‘非’,需要拆分成如下形式:

注意:千万不能直接用 a > b

bool GT(double a, double b) {   // GreaterThan
  return a > b && NEQ(a, b);
}
 
 
 
 

a3b64c55a26f421588d3132d032a6136.gif

如果你年满18周岁以上,又觉得学【C语言】太难?想尝试其他编程语言,那么我推荐你学Python,现有价值499元Python零基础课程限时免费领取,限10个名额!
▲扫描二维码-免费领取

3cab1ca0f270006f80edd9d84e754764.gif

戳“阅读原文”我们一起进步

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值