浮点数相加的舍入问题

#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语言不曾见过或者不熟悉的几个地方。

  1. atof()函数,之前讲过atoi()函数,其实差不多,之前的“i”表示int。而这个“f”表示float。所以这个函数是将char型转化为float型。
  2. sprintf()函数,这个函数和printf()很相似,只不过printf是在控制台打印内容,而sprintf是在该函数的第一个参数地址空间打印内容,后面就与printf很相似了。值得一说的是第一个参数,在上述代码中,用的是数组名,而数组名表示的是数组的第一个元素,即将后面的x保存到prefix[0]中。
  3. strcat()函数是string.h中包含的函数,该函数有两个参数,功能是将第1个参数的字符串与第2个参数的字符串拼接,然后存到第一个参数中。
  4. 再要说的就是按%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 了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值