CS:APP Data Lab Report

CS:APP Data Lab Report

Name SUNCHAOYI

Introduction

This report documents the solutions to the CS:APP Data Lab problems. The goal of the lab is to solve a series of programming puzzles under strict constraints, using only a limited set of C operators to manipulate integer and floating-point bit patterns.

Report

  1. bitXor

    Description: x⊕yx \oplus yx⊕y.

    Legal ops: ~ &

    Solution:

    • Ops = 8

      A⊕B=A‾B∪AB‾=A‾B‾∩AB‾‾‾ \begin{align*} A \oplus B &= \overline{A} B \cup A \overline{B} \\ &= \overline{\overline{\overline{A} B} \cap \overline{A \overline{B}}} \\ \end{align*} A⊕B=AB∪AB=AB∩AB

      cpp 复制代码
      int bitXor (int x,int y)
      {
          int a = ~((~x) & y);
          int b = ~(x & (~y));
          return ~(a & b);
      }
    • Ops = 7 (Opt.)

      A⊕B=(A∪B)∩A∩B‾=A‾∩B‾‾∩A∩B‾ \begin{align*} A \oplus B &= (A \cup B) \cap \overline{A \cap B} \\ &= \overline{\overline{A} \cap \overline{B}} \cap \overline{A \cap B}\\ \end{align*} A⊕B=(A∪B)∩A∩B=A∩B∩A∩B

      cpp 复制代码
      int bitXor (int x,int y) {return ~(~x & ~y) & ~(x & y);}
  2. tmin

    Description: Return minimum two's complement integer.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    cpp 复制代码
    int tmin (void) {return 1 << 31;}
  3. isTmax

    Description: Returns 1 if xxx is the maximum, two's complement number, and 0 otherwise.

    Legal ops: ! ~ & ^ | +

    Solution:

    • The maximum two's complement integer TmaxT_{\text{max}}Tmax has the property x+1=∼xx + 1 = \sim xx+1=∼x, i.e. (x+1)⊕(∼x)=0(x + 1) \oplus (\sim x) = 0(x+1)⊕(∼x)=0.

    • x=−1x = -1x=−1 is a special case (0xffffffff\texttt{0xffffffff}0xffffffff) that need to be excluded.

    cpp 复制代码
    int isTmax (int x) {return !((~(x + 1)) ^ x) & !!(x + 1);}
  4. allOddBits

    Description: Return 1 if all odd-numbered bits in word set to 1.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    Construct a number whose odd-numbered bits are all 1, i.e. the 32-bit pattern 0xAAAAAAAA\texttt{0xAAAAAAAA}0xAAAAAAAA.

    • Ops = 9

      cpp 复制代码
      int allOddBits (int x)
      {
          int mask = (0xAA << 24) | (0xAA << 16) | (0xAA << 8) | 0xAA;
          return !((x & mask) ^ mask);
      }
    • Ops = 7 (Opt.)

      cpp 复制代码
      int allOddBits (int x)
      {
          int a = 0xAA << 8;
          int b = a | 0xAA;
          int c = b << 16 | b;
          return !((x & c) ^ c);
      }
  5. negate

    Description: Return −x-x−x.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    {x+(−x)=0x+(∼x)=−1⟹−x=(∼x)+1 \begin{cases} x + (-x) = 0\\ x + (\sim x) = -1 \end{cases} \Longrightarrow -x = (\sim x) + 1 {x+(−x)=0x+(∼x)=−1⟹−x=(∼x)+1

    cpp 复制代码
    int negate (int x) {return (~x) + 1;}
  6. isAsciiDigit

    Description: Return 1 if 0x30≤x≤0x390x30 \le x \le 0x390x30≤x≤0x39 (ASCII codes for characters 0 to 9).

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    • Upper 24 bits must be zero.

    • Bits 4-7 must equal 0011.

    • Lower 4 bits must be in range 0000 to 1001. (Check whether bit 3 is 0 to have more detailed classification.)

    • Ops = 14

      cpp 复制代码
      int isAsciiDigit (int x)
      {
          int a = !(x >> 8); 
          int b = !(x >> 4 ^ 0x3);
          int low = x & 0xF;
          int c = !(low >> 3) | !(low >> 1 ^ 0x4);
          return a & b & c;
      }
    • Ops = 7 (Opt.)

      • No need to use variable aaa to checker upper 24 bits.

      • use +6 to bound lower 4 bits within 1111.

      cpp 复制代码
      int isAsciiDigit (int x)
      {
          int a = x >> 4 ^ 3;
          int b = ((x & 0xF) + 6) >> 4;
          return !(a | b);
      }
  7. conditional

    Description: Same as x ? y : z.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    • Convert any non-zero xxx to boolean.

    • Create a mask that is either all zeros (0x00000000\texttt{0x00000000}0x00000000) or all ones (0xFFFFFFFF\texttt{0xFFFFFFFF}0xFFFFFFFF).

    • Use the mask to select between −y-y−y and −z-z−z.

    • Ops = 14

      cpp 复制代码
      int conditional (int x,int y,int z)
      {
          int op = !!x;
          int a = (~op) + 1;
          int b = (~a) & ((~y) + 1); // when mask = 0x00000000, b = -y; otherwise b = 0
          int c = a & ((~z) + 1); // when mask = 0xFFFFFFFF, c = -z; otherwise c = 0
          return y + z + b + c;
      }
    • Ops = 8 (Opt.)

      cpp 复制代码
      int conditional (int x,int y,int z)
      {
          int mask = (~(!!x)) + 1;
          return (y & mask) | (z & (~mask)); // one side must equal to 0
      }
  8. isLessOrEqual

    Description: If x≤yx \le yx≤y then return 1, else return 0.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    • Different signs: If xxx is negative and yyy is non-negative, then x≤yx \leq yx≤y is always true.
    • Same signs: We can safely compute y−xy - xy−x without overflow and check if it's non-negative.
    cpp 复制代码
    int isLessOrEqual (int x,int y)
    {
        int signx = x >> 31 & 1;
        int signy = y >> 31 & 1;
        int diff = signx ^ signy;
        int a = diff & signx;
        int b = !diff & !((y + ((~x) + 1)) >> 31); // y - x >= 0
        return a | b;
    }
  9. logicalNeg

    Description: Implement the ! operator using all of the legal operators except !.

    Legal ops: ~ & ^ | + << >>

    Solution:

    • If x=0x = 0x=0, both xxx and −x-x−x have sign bit 0. Otherwise either xxx or −x-x−x have sign bit 1.

    • x∣(−x)x | (-x)x∣(−x) is 0x00000000\texttt{0x00000000}0x00000000 or 0xFFFFFFFF\texttt{0xFFFFFFFF}0xFFFFFFFF, just add 1 to solve it.

    cpp 复制代码
    int logicalNeg (int x) {return ((x | ((~x) + 1)) >> 31) + 1;}
  10. howManyBits

    Description: Return the minimum number of bits required to represent xxx in two's complement.

    Legal ops: ! ~ & ^ | + << >>

    Solution:

    • For x<0x < 0x<0 find the highest 0-bit, x≥0x \ge 0x≥0 find the highest 1-bit. Use x ^ (x >> 31) to transform xxx into the latter case.

    • Use divide-and-conquer approach for the most significant 1-bit, and finally add the sign bit.

    cpp 复制代码
    int howManyBits (int x)
    {
        int b16,b8,b4,b2,b1,b0;
        x = x ^ (x >> 31);
        b16 = (!!(x >> 16)) << 4;
        x >>= b16;
        b8 = (!!(x >> 8)) << 3;
        x >>= b8;
        b4 = (!!(x >> 4)) << 2;
        x >>= b4;
        b2 = (!!(x >> 2)) << 1;
        x >>= b2;
        b1 = !!(x >> 1);
        x >>= b1;
        b0 = x;
        return b16 + b8 + b4 + b2 + b1 + b0 + 1; // sign
    }
  11. floatScale2

    Description: Return bit-level equivalent of expression 2×f2 \times f2×f for floating point argument fff.

    Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while.

    Solution:

    • Extraction the sign bit, exponent field and fraction field.

    • When exp=0xFFexp = \texttt{0xFF}exp=0xFF, just return it; When exp=0x00exp = \texttt{0x00}exp=0x00, frac×2frac \times 2frac×2; otherwise exp+1exp + 1exp+1.

    cpp 复制代码
    unsigned floatScale2 (unsigned uf)
    {
        unsigned sign = uf >> 31 & 0x1;
        unsigned exp = (uf >> 23) & 0xFF;
        unsigned frac = uf & 0x7FFFFF;
        if (exp == 0xFF) return uf;
        else if (exp == 0x0) frac <<= 1;
        else ++exp;
        return (sign << 31) | (exp << 23) | frac;
    }
  12. floatFloat2Int

    Description: Return bit-level equivalent of expression (int) fff for floating point argument fff.

    Legal ops: Any integer/unsigned operations incl. ||, &&. Also if, while.

    Solution:

    Converting to integer with truncation:
    int(f)={0if ∣f∣<1trunc(1.f×2e−127)if 1≤∣f∣<231INT_MINotherwise (overflow) \text{int}(f) = \begin{cases} 0 & \text{if } |f| < 1 \\ \text{trunc}\left(1.f \times 2^{e-127}\right) & \text{if } 1 \leq |f| < 2^{31} \\ \text{INT\_MIN} & \text{otherwise (overflow)} \end{cases} int(f)=⎩ ⎨ ⎧0trunc(1.f×2e−127)INT_MINif ∣f∣<1if 1≤∣f∣<231otherwise (overflow)

    Where truncation is implemented by:

    • When E≥23E \geq 23E≥23: 1.f×2E=(1.f×223)×2E−231.f \times 2^{E} = (1.f \times 2^{23}) \times 2^{E - 23}1.f×2E=(1.f×223)×2E−23
    • When E<23E < 23E<23: Right shift discards fractional bits, i.e. >>(23−E)>> (23 - E)>>(23−E)
    cpp 复制代码
    int floatFloat2Int (unsigned uf)
    {
        unsigned sign = uf >> 31 & 0x1;
        unsigned exp = (uf >> 23) & 0xFF;
        unsigned frac = uf & 0x7FFFFF;
        int E,M;
        E = exp - 127;
        if (E < 0) return 0;
        if (E >= 31) return 0x80000000u;
        M = (1 << 23) | frac;
        if (E >= 23) M <<= E - 23;
        else M >>= 23 - E;
        return sign ? -M : M;
    }
  13. floatPower2

    Description: Return bit-level equivalent of the expression 2.0x2.0^x2.0x (2.0 raised to the power xxx).

    Legal ops: AAny integer/unsigned operations incl. ||, &&. Also if, while.

    Solution:

    • Case 1 : Overflow

      x>Emax⁡=e−127=254−127=127x > E_{\max} = e - 127 = 254 - 127 = 127x>Emax=e−127=254−127=127

      return 0b01111111100...0\texttt{0b01111111100...0}0b01111111100...0, i.e. 0x7F800000\texttt{0x7F800000}0x7F800000

    • Case 2 : Normalized

      e=E+127∈[1,254]⟹E∈[−126,127]e = E + 127 \in [1,254] \Longrightarrow E \in [-126,127]e=E+127∈[1,254]⟹E∈[−126,127]

      V=1.0×2e−127V = 1.0 \times 2^{e - 127}V=1.0×2e−127

      f=0,V←(e<<23)∣ff = 0,\quad V \gets (e << 23) | ff=0,V←(e<<23)∣f

    • Case 3 : Denormalized

      e=0e = 0e=0

      V=0.f‾×2−126=2x⟹0.f‾=2x+126V = \overline{0.f} \times 2^{-126} = 2^x \Longrightarrow \overline{0.f} = 2^{x + 126}V=0.f×2−126=2x⟹0.f=2x+126

      minimum number is 2−126×2−23=2−1492^{-126} \times 2^{-23} = 2^{-149}2−126×2−23=2−149, i.e. put 1 on index 0.

      ⟹V←1<<(x+149)\Longrightarrow V \gets 1 << (x + 149)⟹V←1<<(x+149)

    • Case 4 : Underflow

      x<−149x < -149x<−149, return 0

    cpp 复制代码
    unsigned floatPower2 (int x)
    {
        if (x < -149) return 0;
        else if (x > 127) return 0x7F800000;
        else if (x >= -126) return (x + 127) << 23;
        else return 1 << (x + 149);
    }

复制代码
Correctness Results     Perf Results
Points  Rating  Errors  Points  Ops     Puzzle
1       1       0       2       7       bitXor
1       1       0       2       1       tmin
1       1       0       2       8       isTmax
2       2       0       2       7       allOddBits
2       2       0       2       2       negate
3       3       0       2       7       isAsciiDigit
3       3       0       2       8       conditional
3       3       0       2       14      isLessOrEqual
4       4       0       2       5       logicalNeg
4       4       0       2       32      howManyBits
4       4       0       2       12      floatScale2
4       4       0       2       16      floatFloat2Int
4       4       0       2       9       floatPower2

Score = 62/62 [36/36 Corr + 26/26 Perf] (128 total operators)
相关推荐
梁辰兴1 天前
计算机网络基础:吉比特以太网
网络·计算机网络·计算机·以太网·计算机网络基础·梁辰兴·吉比特以太网
在路上看风景2 天前
06. 提高缓存命中率
计算机
程序员鱼皮4 天前
女友怒骂国内不能用Claude Code,于是我给她做了一个
计算机·ai·程序员·大模型·互联网·编程
驱动探索者5 天前
[缩略语大全]之[编译器]篇
计算机·状态模式·飞书·编译器
驱动探索者5 天前
[缩略语大全]之[计算机图形学]篇
计算机·显示器·图形学·显示
程序员鱼皮6 天前
突发,快手被色情直播刷屏!背后的原因竟然是?
计算机·程序员·互联网·编程·事故
梁辰兴6 天前
计算机网络基础:以太网的 MAC 层
网络·计算机网络·macos·计算机·mac·以太网·梁辰兴
程序员鱼皮7 天前
从夯到拉,锐评 28 个后端技术!
后端·计算机·程序员·开发·编程经验
梁辰兴7 天前
计算机网络基础:局域网的数据链路层
网络·网络协议·计算机网络·计算机·数据链路层·局域网·梁辰兴