CSAPP学习日志----(x+y)+z = x+(y+z)?

我在CMU的官网上看到这样一个问题:
( x + y ) + z = x + ( y + z ) ?
那么答案应该是怎么样的呢?是正确的吗?
我们可以用这段代码来测试这个问题的答案。
先上代码:

#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);/*sprintf格式化输出
	  %g将采用可以表示为%f(简单浮点数或双精度数)或%e(科学计数法)的数字,并从两者中选择合适的。*/
	} else {
	  sprintf(next, " + %.4g", x);
	  strcat(prefix, next);
	  printf("%s = %.4g\n", prefix, sum);
	}
    }
    return 0;
}

博主在这里对以上代码进行一些说明:

1.相信没有接触过linux的人可能会对int main(int argc, char *argv[ ])有所困惑,
第一个int argc,是记录你输入在命令行上的字符串个数;
第二个 *argv[ ]是个指针数组,存放输入在命令行上的命令(字符串)。
argv[ ] 是一个字符数组.
argv[0]:指向程序的名称
argv[1]:指向程序名后的第一个字符串。

2.对于第十三行中的 atof ,这是c的一类自带库函数(<stdio.h>里的)
atof:用于将字符串转换为双精度浮点数 (double) 型; atoi:将字符串转换为整型数 (int) 型;atol:将字符串转换为长整型数 (long) 型
同理,对于strcat是c自带库函数(<string.h>里的)
strcat的用法:strcat(字符串1,字符串2)
strcat是一个函数.是字符串连接的意思. 起作用是连接两个字符数组中的字符串.
把字符串2接到字符串1的后面,结果放在字符串1中.
这个函数调用后得到一个函数值:字符串1的地址

3.第十六行的代码 sprintf(prefix, “%.4g”, x) 其中 sprintf 是格式化输出,%g将采用可以表示为%f(小数)或%e(科学计数法)的数字,并从两者中选择合适的。(这一点我在代码中给出了注释)


程序运行结果如下:

gec@ubuntu:/mnt/hgfs/gx$ ./fsum 1e20 -1e20 3.14
1e+20 + -1e+20 = 0
1e+20 + -1e+20 + 3.14 = 3.14
gec@ubuntu:/mnt/hgfs/gx$ ./fsum -1e20 3.14 1e20
-1e+20 + 3.14 = -1e+20
-1e+20 + 3.14 + 1e+20 = 0

显然,程序运行结果中:

(1e+20 + -1e+20) + 3.14 = 3.14
-1e+20 + (3.14 + 1e+20) = 0

因此该程序说明 (x+y)+z != x+(y+z)
为什么呢?为什么会出现这种结果呢?
(在解释这个情况之前读者最好掌握浮点数的相关知识,了解了之后在再看下面的解释)

因为浮点数在运算前会先进行对阶,在对阶时我们会对尾数进行位移以此保证改变阶码后数的值仍不变,我们设想相加的两个数阶码差过大,对阶时就会出现小的数尾数进行位移操作后全部为0,所以小数就为0了,当阶码数相差过大时,会舍弃较小的数
因此运算(-1e+20) + 3.14时,3.14被舍,运算结果为 -1e+20,运算1e+20 + 3.14时,3.14被舍,运算结果为 1e+20。
这才导致出现了(x+y)+z != x+(y+z)的情况发生。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值