C/C++中值得注意的小Trick
进入大学,开始学C语言,开个博客来记录学习中值得注意的地方

第一篇博文,准备记录一下C/C++中一些容易踩到坑(那种难搜到的问题,请教别人才弄明白的)。欢迎指正写得不对的地方,本文会持续更新。

浮点数不能直接用==判等

如果想要判断两个浮点数是否相等,直接在if中使用==判断有时会得到错误的结果,比如下例会输出”nope…”

#include <stdio.h>

int main() { 
    float a = 1.23;
    if (a == 1.23) {
        printf("yes, babe");
    } else {
        printf("nope...");
    }
    return 0;
}

其原因是,浮点数在计算机里表示的形式不像整形那样简单。

float单精度浮点数在计算机里面表示形式由3部分组成符号位(1位),指数位(8位),尾数部分(23位)。

对于浮点数120.5,用科学记数法表示为1.205*10^2

转换成二进制,1.20510^2 = 1.11011012^6

我们把上面的二进制表达式,看成n*2^m,对应到上面的3个部分就是

符号位,正数为1,负数为0;

指数位,存放表达式中的m值,根据IEEE754规范的规定,m实际存储时,需要加上一个固定值127;

尾数位,存放表达式中的n值,因为n的首位一定是1,n实际存储时,会把第一个1省略掉,所以实际尾数位可以表达24位的内容;

所以,在内存中120.5的二进制表达方式应该是这样的:

符号位是1

指数位,m是6,加上127等于133,所以指数位是10000101

尾数位,n是1.1101101,去掉第一个1,那么尾数为是1101101,后面空着的位都补0。

所以120.5在内存中的表示是0100001011101101000000000000。

回到最初的问题,浮点数使用==判断相等时,程序会直接拿内存储存的内容按位比较。可以看到

这样的表示方式,节省了非常多的空间,但是代价是引入了误差(当尾数位超过24位时)。

所以,浮点数判断相等的正确做法是,将两个数相减之后取绝对值,然后判断这个绝对值是否小于某个值。比如:

#include <stdio.h>

int main() {

    double a = 1.23;

    if (fabs(a - 1.23) < 1e-7) {
        printf("yes, babe");
    } else {
        printf("nope...");
    }
    return 0;

}

至此,问题基本解决。

感谢某不愿透露姓名的+7学弟,还有1e-7这种高端写法也是这位某学弟教我的- -

*****
Written by Prince Laharl on 07 November 2015