浮点数相加的舍入问题

    xiaoxiao2025-02-14  38

    #include <stdio.h> #include <stdlib.h> #include <string.h> #define BUFSIZE 256 int main(int argc, char *argv[]) { char prefix[BUFSIZE]; char next[BUFSIZE]; int i; float sum = 0.0; for (i = 1; i < argc; i++) { float x = atof(argv[i]); sum += x; if (i == 1) { sprintf(prefix, "%.4g", x); } else { sprintf(next, " + %.4g", x); strcat(prefix, next); printf("%s = %.4g\n", prefix, sum); } } return 0; }

    这段代码有几个之前学C语言不曾见过或者不熟悉的几个地方。

    atof()函数,之前讲过atoi()函数,其实差不多,之前的“i”表示int。而这个“f”表示float。所以这个函数是将char型转化为float型。sprintf()函数,这个函数和printf()很相似,只不过printf是在控制台打印内容,而sprintf是在该函数的第一个参数地址空间打印内容,后面就与printf很相似了。值得一说的是第一个参数,在上述代码中,用的是数组名,而数组名表示的是数组的第一个元素,即将后面的x保存到prefix[0]中。strcat()函数是string.h中包含的函数,该函数有两个参数,功能是将第1个参数的字符串与第2个参数的字符串拼接,然后存到第一个参数中。再要说的就是按%g输出是什么意思,根据数据的绝对值大小,自动选取f或e格式中输出宽度较小的一种使用,且不输出无意义的0。 再看输出结果 hxl@hxl-virtual-machine:~/桌面/task/code$ gcc -o fsum.c hxl@hxl-virtual-machine:~/桌面/task/code$ ./f 1e20 3.14 1e+20 + 3.14 =1e+20

    一看就发现与平时所想不同,怎么会有一个数与另一个不为0的数相加还等于自己。这就涉及到计算机中浮点数的存储和浮点数相加的规则了。float型变量在计算机中用32位表示,其中第1位表示符号位,而后8位用来表示阶码,最后23位用来表示尾数。两个浮点数相加最先做的就是进行对阶操作,意思就是让两个阶码不同的浮点数变成两个阶码相同的浮点数。如果两个浮点数的阶码相差太大,则会导致其中阶码小的,通过将小数点向左移动来增大阶码,这样一来位数的23位可能就不够表示,意思是可能导致有效数字流失。最后得到的尾数就都是0了。这样两个浮点数再相加,就相当于一个大的加了个0。自然上面的1e+20 与 3.14 相加也就等于1e+20 了。

    最新回复(0)