CSAPP data Lab
注意,本文代码出于节省括号避免繁杂的考虑,对运算符优先级利用得比较充分,比如 1>>n+1 等价于 1>>(n+1),所以代码里写了1>>n+1。
bitAnd
1 | /* |
思路
- 德摩根定律
getByte
1 | /* |
思路
- 移位到最低的1byte然后用0xFF提取
logicalShift
1 | /* |
思路
因为不能用
-
,所以用取反加一代替取负构造低
32-n
bit的1来提取移位后的数值因为移位量不能小于0或大于等于32,所以对于n可能是0而导致移位量是32的情况,先移位31位,再移位1位
小技巧,如果n移位k,k$\in$[0, 32],则可以
n>>(k-!!k)>>!!k
bitCount
1 | /* |
思路
- 构造0x55555555,提取每两位中的low bit。通过移位及0x55555555,提取每两位中的高位。然后相加,使得结果中,每两位的二进制值就是该两位的bit数目
- 同样的思路,提取每四位的low bit、high bit,然后相加
- 因为32==100000(二级制),也就是只需要5位就可以记录有多少bit数,所以不需要每次都构造常数屏蔽高位的值,直接移位相加然后取低8bit就可以得到最终结果
bang
1 | /* |
思路
- 如果非0,位模式从最高位的1到最低位都填充为1,
- 如果为0,则位模式还是保持全0
tmin
1 | /* |
fitBits
1 | /* |
思路
- 算术移n-1位,如果是负数,且可以用n bits的补码表示,则得到-1。如果是正数,则得到0。
divpwr2
1 | /* |
思路
- 直接移位是round down,无论是负数还是正数
- 所以要实现round to zero , C表达式为
x<0 ? x+(pow(2,n)-1)>>n : x>>n
negate
1 | /* |
思路
- 直接取反再加1
isPositive
1 | /* |
思路
- 符号位判断,并且非0
isLessOrEqual
1 | /* |
思路
x<0&&y>0 | !(x>0&&y<0)&&(x-y>0) | x==y
ilog2
1 | /* |
思路
- 先构造从最高的1到最低位均为1的二进制,然后类似bitCount
float_neg
1 | /* |
思路
- 判别是否是NaN。先判断尾数是否全0,然后用
(t>>23)+1>>8
判断exp是否全1
float_i2f
1 | /* |
思路
分情况处理0、负数、正数
要处理舍人
- 向接近的舍入
- 如果处于中间,向偶数舍入
舍入时,如果尾数加一,exp有可能需要进位,这时候直接加一效果一样,可以导致exp进位,不需要特殊处理。如果exp等于0xFE,那么进位就变成了inf,也是合法的
float_twict
1 | /* |
思路
- 分情况处理三种IEEE754的情况
- 需要注意exp全0时,乘以二就是尾数乘以二,如果发生进位需要exp进位,不需要特殊处理(第三个if),因为进位直接导致exp加一,这就足够了