CSAPP 第二章 datalab
哦我的上帝实验怎么是英文版的😶🌫️
上周小学期一直做项目没学习,正好做做实验复习一下
int
bitXor
题目要求:只使用 ~ 和 & 来实现 ^ 操作
复习环节
~ 按位非(每位二进制取反),& 按位与(对应位同为1结果位才为1),| 按位或(只要有一位是1结果位就是1),^ 亦或(对应位相同为0,不同为1)
首先可以想到 x^y = x&~y + ~x&y = (x&~y)|(~x&y)
接下来想办法替代 |
,x|y=~(~x&~y)
,所以最后的结果是:
1 |
|
tmin
题目要求:使用 ! ~ & ^ | + << >> 来获取 int 的最小值
复习环节
!逻辑非,<< 左移, >> 右移
最小值其实就是1后面31个0,但我们不能使用超过 8bit 的常数。可以使用左移运算,让初始常数1左移31位。
1 |
|
isTmax
题目要求:判断 x 是不是 int 的最大值
复习环节:
! 逻辑非,将非零数值转换为1,而 0 保持不变
根据上题我们得出最小值,取反就能得到最大值也就是 ~(1<<32)
。
如果 x 和最大值一样,那么每一位都是一样的的,我们就可以使用异或操作如果两边相等就返回 0,最后逻辑非将0转化为1就行。
1 |
|
allOddBits
题目要求:判断所给出的数字奇数位是否都为 1 。
根据题目提示0xAAAAAAAA的奇数位都是1,偶数位都是0,我们考虑直接用它来和原来的数字进行按位与运算再和AAA异或。但又由于位数不能超过 8 bit,需要利用左移运算,左移以后再和原来的值进行与运算。
1 |
|
negate
题目要求:取目标数值的相反数
负数就是按位取反以后加一
1 |
|
isAsciiDigit
题目要求:如果 0x30 <= x <= 0x39,则返回 1
判断目标值和已知数值的大小只要做减法就可以,但是这个式子不能用 - ,考虑按照上题方法取反后相加,再看结果值符号位的正负即可。
括号一定要括对😿
1 |
|
conditional
题目要求:实现 x ? y : z (x 不为 0 返回 y ,为 0 返回 z )
对于 x 是否为0,我们可以采用两次 ! 运算来实现即 !!0=0
,!!3=1
。
我们知道,任何书与所有位全是1的值的结果都是它本身,同样与位全是0的数就是0。根据掩码的规范,所有位都是 1 的值是十进制的 -1,所以我们需要对逻辑与之后的结果取倒数就是 (~!!x+1)
。
1 |
|
isLessOrEqual
题目要求:如果 x <= y 则返回 1,否则返回 0
本来想的是像前面的题一样直接相减就行了,但是想到可能会有溢出的问题。
解决方法是先判断符号位,如果两个数符号相同再做差,符号不同就可以直接返回结果了。
正负 | sign_x | sign_y | 返回值 |
---|---|---|---|
x正 y负 | 0 | 1 | 0 |
y正 x负 | 1 | 0 | 1 |
观察结果可以发现返回值就等于 sign_x&(!sign_y)
。
还需要考虑两个数相等的情况,相等时符号位为 0 。可以转换思路绕过这个情况,在数据都是整数时 x<=y
也就是 x<y+1
,所以做差的计算式就变成了 x+(~y+1)-1
也就是 x+~y
。
1 |
|
logicalNeg
题目要求:实现逻辑非的功能
逻辑非无非就是需要想一想 0 和非零数之间的区别。0 的正负数都相等,但是其他数的正负不同,我们可以利用这个特性将目标数据取相反数后异或,再判断符号位,相同返回 0,不同返回 1 。
由于符号位为 1 ,右移后的结果便为0x11111111, 令其加 1 ,刚好为 0(这是因为在补码表示法中,负数的绝对值可以通过取反加1来获得)
1 |
|
howManyBits
题目要求:返回表示 x 所需的最小位数
这道题完全没思路,是看别的师傅的博客才明白的
首先让所有的数据都变成正值,然后利用二分法来判断二分后的最高位是否全是0,再判断是否全是1。
1 |
|
float
floatScale2
题目要求:将传入的无符号整型数转换为浮点数 f*2
返回
复习环节:
浮点数有三部分,符号 s(最高位) ,阶码 exp(八位)和 尾数 frac。
先分为三个部分,再分不同条件进行判断
exp==0
此时浮点数的值是一个接近于 0 的二进制小数,可以通过将尾数部分左移 1 位来将其乘以 2。然后,将符号位重新添加回去,得到乘以 2 后的规格化浮点数。
exp==255
按题目要求直接返回 uf
其他情况
exp 指数加1,对它乘2^1也就是乘2
1 |
|
floatFloat2Int
题目要求:将目标 float 数据强制转换为 int 型数据。
这道题一开始写错了,又灰溜溜去找解析🤐
找了一张这样的图看上去更直观一点
exp=0
,也就是阶码全是0的非规格化数,此时E=1- (128-1)= -126
,我们认为这是一个非常接近 0 的数,所以可以直接return 0
exp=255
,也就是 0XFF 最大值,特殊值NaN直接返回整数型的最大值return 0x80000000u
exp!=0&&exp!=255
,也就是规格化的情况。此时E=exp-127
,又分为下面几种情况:- E < 0 时,V<1,
return 0
- E >= 23,则进行加权时,需要 frac 左移
(E-23)
位 - 0 < E < 23,需要FRAC右移
(23-E)
位 - E > 31,Infinity 直接
return 0
- E < 0 时,V<1,
1 |
|
floatPower2
题目要求:实现 pow(2,x)
,返回结果为 unsigned
因为题目是实现2的阶乘,我们直接在二进制的基础上左移就行
1 |
|
复习题目可以发现很多读书漏掉的重要东西
第一次做完实验也就浅浅错了三道题 11 个测试罢了🥲
最后一道题总是TIMEOUT,看了别的师傅的也是这样干脆改了 btest.c
里的时限
完结撒花撒花~