CSAPP Datalab
实验环境
Ubuntu 12.04.5。
bitAnd
德摩根律。
|
|
getByte
要取第 n 个字节,将 x 右移 n*8 位,再去除多余字节即可。
|
|
logicalShift
算数右移 n 位,并构造形如 0…01…1 的二进制串,将左边填充的 n 位清 0。 构造方法:将 1 « 31 取反得到 0x7fffffff,对于 n >= 1,将 0x7fffffff 右移 n - 1 位完成构造。但对于 n = 0,不能右移 -1 位,这是未定义行为。故最终方案为将 0x7fffffff 右移 n 位,再左移 1 位、加 1,完成构造。
|
|
bitCount
分解子问题。先求每 2 位有几个 1,再求每 4 位有几个 1,再求每 8 位有几个 1,再求每 16 位有几个 1,最后求所有 1 的个数。
|
|
bang
- 对于非 0 数,其与自己相反数相或,最高位为 1,算数右移 31 位得到 0xffffffff,再加 1 则变为 0。
- 对于 0,其与自己相反数相或,最高位为 0,算数右移 31 位得到 0x0,再加 1 则变为 0x1。
|
|
tmin
补码可表示的最小值:最高位为 1,其余位为 0。
|
|
fitsBits
将 x 左移 32 - n 位,再右移 32 - n 位,若没有数据丢失,则满足题意。
|
|
divpwr2
- x > 0 时,直接右移 n 位。
- x < 0 时,需要加上偏置量保证除法结果向 0 取整。
|
|
negate
相反数可表示为原数取反再加 1,可以由一个数和它的相反数相加为 0 推出此结论。
|
|
isPositive
逆向思维,先找出 x <= 0 的情况。 当 x = 0 时,!x 为 1;当 x < 0 时,x 的符号位为 1。不满足这两种情况,则 x > 0。
|
|
isLessOrEqual
满足 x <= y 的情况如下:
-
x、y 同号时,y - x 的符号位为 0。
-
x、y 异号时,x 负 y 正。
|
|
ilog2
采用二分思想,每一行的 t 计算的都是 x 的最高位的 1 至少在哪一位。 在已确定有 1 的 32 位中,若高 16 位有 1,则 t1 = 16,否则 t1 = 0。 在已确定有 1 的 16 位中,若高 8 位有 1,则 t2 = t1 + 8,否则 t2 = t1。 在已确定有 1 的 8 位中,若高 4 位有 1,则 t3 = t2 + 4,否则 t3 = t2。 在已确定有 1 的 4 位中,若高 2 位有 1,则 t4 = t3 + 2,否则 t4 = t3。 在已确定有 1 的 2 位中,若高 1 位有 1,则 t5 = t4 + 1,否则 t5 = t4。 t5 即为最终结果。
|
|
float_neg
视 uf 的值而定。
- NaN:若阶码为全 1,尾数不全为 0,则 uf 为 NaN,直接返回 uf。
- 其他:符号位与 1 异或,实现取反即可。
|
|
float_i2f
- x == 0:返回 0。
- x != 0:通过左移找到 x 的绝对值(absx)的位表示的第一个 1,用 cnt 记录 absx 第一个 1 前有多少个 0,当第一个 1 左移到最高位时,开始计算阶码和尾数。
- 阶码:exp = E + bias = (31 - cnt) + 127 = 158 - cnt。再左移 23 位,方便拼接结果。
- 尾数:absx 的第一个 1 已经左移到最高位,我们再把 absx 右移 8 位,这样,第一个 1 就到了第 31 - 8 = 23 位,后面的第 22 ~ 0 位存入 frac。 接着拼接符号位、阶码和尾数,得到一个未舍入的结果。
- 最后考虑舍入问题。absx 的第一个 1 已经左移到最高位,后面的连续 23 位是可以精确表示的,31 - 1 - 23 = 7,因此我们要对 absx 的第 7 ~ 0 位,即低 8 位考虑舍入问题。如果低 8 位大于 0x80,向上舍入,结果加 1;如果低 8 位等于 0x80,则考虑 frac 的末位是否为 1,若是,则向上舍入,结果加 1;除此之外,低 8 位舍弃。
|
|
float_twice
先取出符号位和阶码,再分类讨论。
- 阶码为全 0:将 uf 左移 1 位,再补上符号位。这样指数不变,尾数向高权值位移动,实现乘 2。
- 阶码不为全 0,也不为全 1:uf 阶码部分加 1,即 uf + 0x800000。再补上符号位。这样尾数不变,指数加 1,实现乘 2。因为规格化值和非规格化值从二进制串映射到浮点数的方法有所不同,所以该情况和阶码全为 0 的情况采用不同的方法。
- 阶码为全 1:不做改变。
|
|