C++ 浮点数精度判定
Posted C和C加加
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ 浮点数精度判定相关的知识,希望对你有一定的参考价值。
来源:blog.csdn.net/WhereIsHeroFrom
一、引例
看下下面这段代码,会输出什么结果呢?
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)),以及这些数值的“浮点数运算符”。
基于这个规定,任何浮点数都可以表示成如下形式:
2、单精度和双精度
C++ 中两种浮点数,float 和 double,分别代表单精度和双精度;
单精度尾数占23个比特位,指数占8个比特位;双精度尾数占52个比特位,指数占11个比特位;
由于结构相同,这里只介绍单精度浮点数;
3、单精度浮点数表示法
如图为 32位 的浮点数的二进制表示,总共 32 个比特位(取值 0 或 1);
S 在最高位,代表符号,负数为1,正数为0;
E 为从高到低的第 30 - 23 位,总共 8 位,代表指数偏移,存储的是加上了 127 以后的值(原因是指数有可能是负数);
F 代表二进制科学计数法的尾数,总共 23 位,因为是科学计数法,所以开头一定是 “1.” 开头,所以尾数有效位数为 24 位;
4、举例说明
【示例】 对于−18.375这个浮点数,求出它的二进制存储格式;
5、代码测试
float a = -18.375;
unsigned int v = *((unsigned int *)&a);
三、浮点数判定
1、精度定义
#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);
}
简单分享快乐学习,如有错误请多包涵!
PS:如果没有你的关注,那我所做的将毫无意义!欢迎分享,点赞,在看。
以上是关于C++ 浮点数精度判定的主要内容,如果未能解决你的问题,请参考以下文章
将(n个第一个字节)无符号字符指针转换为浮点数和双精度C++