【紫书】第一章实验+问题

紫书第1章实验

实验A1:表达式 11111 ∗ 11111 11111\ast11111 1111111111的值是多少?改成6个1呢?9个1呢?

以下几个都用有符号整数 % d \%d %d输出结果。

表达式 11111 ∗ 11111 11111\ast11111 1111111111的值为 123454321 123454321 123454321。不越界,所以得到了正确结果。

把5个1改成6个1,结果变成了 − 539247567 -539247567 539247567,原因是,原本的结果是 111111 ∗ 111111 = 12345654321 > 2 31 − 1 = 2147483647 111111\ast111111=12345654321>2^{31}-1=2147483647 111111111111=12345654321>2311=2147483647,产生了越界,所以 i n t int int的32位上的结果是 12345654321 % 2 32 = 3755719729 = 2 31 + 1608236081 12345654321\%2^{32}=3755719729=2^{31}+1608236081 12345654321%232=3755719729=231+1608236081,由 i n t int int负数的补码表示规则,第一位是符号位,所以输出的值为 − 2 31 + 1608236081 = − 539247567 -2^{31}+1608236081=-539247567 231+1608236081=539247567,和试验结果相符。

把5个1改成9个1,显然更是越界的,得到的结果是 1653732529 = ( 111111111 ∗ 111111111 ) % 2 32 1653732529=(111111111\ast111111111)\%2^{32} 1653732529=(111111111111111111)%232,相符。

如果改成 % f \%f %f,都会输出 0.000000 0.000000 0.000000,这涉及到浮点数的保存方法,由于 % f \%f %f是自动寻64位内存的,所有 i n t int int型的数都在后32位尾数里,都很小, % f \%f %f自动保留6位小数之后都是 0.000000 0.000000 0.000000

实验A2:把实验A1中的所有数换成浮点数,结果如何?

11111.0 ∗ 11111.0 11111.0\ast11111.0 11111.011111.0为例,如果用 % f \%f %f输出,可以输出正确的结果 123454321.000000 123454321.000000 123454321.000000,因为 % f \%f %f可以表示的数据范围还是挺大的。但是如果改成了 % d \%d %d,结果就变成了 − 272632416 -272632416 272632416。这个结果是因为 123454321 ≈ 1.83961... ∗ 2 26 123454321\approx1.83961...\ast2^{26} 1234543211.83961...226,如果是采用IEEE的标准存储,不出意外这应该是尾数的后32位部分。从实验A1和A2我们显然可以明白 i n t int int f l o a t float float在printf里显然不可以瞎转换。

% d \%d %d输出显然无法得到正确结果,但注意当九个1时,即使用 % f \%f %f输出,结果也会变成 12345678987654320.000000 12345678987654320.000000 12345678987654320.000000,个位出现了1的偏差。究其原因,之前提到浮点数使用幂存储方法, d o u b l e double double类型有53位尾数,而 log ⁡ 2 12345678987654321 \log_212345678987654321 log212345678987654321刚好是53点几,尾数的精确度是 2 − 52 2^{-52} 252,乘上阶数 2 53 2^{53} 253刚好到达个位数量级,所以差不多会开始产生偏差。

实验A3:表达式sqrt(-10)的值是多少?尝试用各种方式输出,在计算的过程中会报错吗?

如果用 d o u b l e double double输出 s q r t ( − 10 ) sqrt(-10) sqrt(10),会得到nan,即not a number,不会报错。

如果用 i n t int int输出 s q r t ( − 10 ) sqrt(-10) sqrt(10),又得到了之前神秘的负数 − 272632416 -272632416 272632416,这应该是一个随机的结果,因为在程序里添加了一段文字之后输出又会变化,其中的转化规则我也不知道,也不重要。因为nan用浮点数表示,阶码部分全是1,小数部分不为0,所以小数部分可以任意取,有很多种。会返回哪一种给 % d \%d %d,我暂时还不知道。

实验A4:表达式1.0/0.0、0.0/0.0的值是多少?尝试用各种方式输出,在计算的过程中会报错吗?

1.0 / 0.0 1.0/0.0 1.0/0.0其实是可以算出来的,用 % f \%f %f输出得到 i n f inf inf,但用 % d \%d %d输出也是一个可变化的结果,我不太理解,照理说 i n f inf inf的浮点表示不是固定的吗?还是这里的浮点数没有采用IEEE的标准?求指教…

0.0 / 0.0 0.0/0.0 0.0/0.0的结果是nan,一般 p r i n t f printf printf输出的时候,能算出来的会输出对应的0或者 i n f inf inf,算不出来的,就是nan。用 % d \%d %d表示的结果就不谈了,也是可变的。

实验A5:表达式1/0的值是多少?在计算的过程中系统会报错吗?

现在可以输出一个随机值,并没有输出 i n f inf inf,因为divided by zero属于系统未定义行为。但我记得以前似乎是会报错的?

实验B1:同一行中输入12和2,并以空格分隔,是否得到预期结果?

可以得到, % d \%d %d会自动寻找整数。

实验B2:在不同两行输入12和2,是否得到预期结果

可以得到,道理同上,该行没有会自动读下一行。

实验B3:在B1和B2中,在12和2的前面和后面插入大量的空格或\t,甚至插入空行

一样可以得到正确的结果。

实验B4:把2换成字符s,重复实验B1~B3

其实换成字符s和打空格没有本质区别,都是一个字符。可以正常输出12,但第二个值就是未定义的了。

思考:如何输出%和d两个字符?

printf("%%d\n");

章末的问题

1. int型整数的最小值和最大值?

-2147483648和2147483647。

2. double型浮点数能精确到多少位小数?或者,这个问题本身值得商榷?

这个问题值得商榷,因为double的精度和前面阶码的大小有关。数据的绝对值越大,精度就越低。

3. double型浮点数最大整数值和最小正数值分别是多少,不必特别精确

如果采用IEEE浮点表示,最小正数是最小的非规格化数,本应该是 2 − 52 ∗ 2 − 1022 2^{-52}\ast2^{-1022} 25221022,但结果却是2的负三百多次方,可能标准变了。。总之差不多在2的几百次方左右。

4.逻辑运算符号“&&”、“||”和“!”的优先级?

查表可知优先级关系是 ! > & & > ∣ ∣ !>\&\&>|| !>&&>

5. if(a) if(b) x++; else y++; else和哪个if配套?

尽管说else匹配的是最近的if,但严格说来应该是同一代码块中最近的if。上述语句等价于

if(a){
		if(b){
    	x++;
  	}
  	else{
      y++;
    }
}

所以配之前的一个。不过这么写代码的也真是牛逼!

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值