数据表示

  • 位操作
    • 基本运算
      • 与、或、非、异或、左移。
      • 逻辑右移:在高位补 00
      • 算术右移:在高位补充之前的最高位数字。
      • 移位量大于等于字长或小于 00 在 C 语言中是未定义行为。
    • 优先级
      • 位运算符优先级:
        • 按位非 ~
        • 左移/右移 << >>
        • 按位与 &
        • 按位异或 ^
        • 按位或 |
      • 结合算术运算时,算术运算符优先级高于移位运算符。
  • 内存布局
    • 字长
      • 字长等于 CPU 的位数。
      • 地址按照字长的倍数对齐。
    • 字节顺序
      • 字节顺序指定多字节数据类型中每个字节的顺序。
      • 大端序:高位在前,低位在后。Internet 使用。
      • 小端序:高位在后,低位在前。x86、ARM 使用。
  • 整数
    • 编码
      • 二进制位向量:底层储存方式,无编码,以下用 BB 表示,记作 [xw1,,x0][x_{w - 1}, \dots, x_0]
      • 无符号整数:把二进制位向量直接解释为整数,以下用 UU 表示。
      • 有符号补码整数:最高位作为符号位,剩下的位储存数或其按位取反加 11,以下用 TT 表示。
      • C 语言标准不强制有符号整数使用补码,但是几乎都是使用补码。
    • 编码解释
      • 对于同一个位向量,使用不同的编码,可以有不同的解释的值。
      • 无符号 B2Uw(x)=i=0wxi2iB2U_w(\boldsymbol x) = \displaystyle \sum_{i = 0}^w x_i 2^i
      • 有符号 B2Tw(x)=xw12w1+i=0w1xi2iB2T_w(\boldsymbol x) = \displaystyle -x_{w - 1} 2^{w - 1} + \sum_{i = 0}^{w - 1} x_i 2^i
      • 逆运算用 U2B(x)U2B(x)T2B(x)T2B(x) 表示。
      • 无符号最值 UMin=0UMin = 0UMax=2w1UMax = 2^{w} - 1
      • 补码最值 TMin=2w1TMin = -2^{w - 1}TMax=2w11TMax = 2^{w - 1} - 1
    • 同大小强制转换
      • 基本原则:在补码和无符号之间转换,底层的位向量不会变,只是改变编码方式。
      • 补码转无符号 T2U(x)=B2U(T2B(x))=x+xw12w={x,x0x+2w,x<0T2U(x) = B2U(T2B(x)) = x + x_{w - 1} 2^w = \begin{cases} x, & x \ge 0 \\ x + 2^w, & x < 0 \end{cases}
        • 非负数和负数转换后,区间顺序颠倒,负数变成大正数。
        • 非负数值不变,1-1 转换为 UMaxUMaxTMinTMin 转换为 TMax+1TMax + 1
      • 无符号转补码 U2T(u)=B2T(U2B(u))={u,u<2w12w+u,u2w1U2T(u) = B2T(U2B(u)) = \begin{cases} u, & u < 2^{w - 1} \\ -2^w + u, & u \ge 2^{w - 1} \end{cases}
      • 在同一个运算符两侧,如果同时存在无符号和补码,则会转换补码为无符号,再进行比较。
    • 扩展
      • 基本原则:扩展前后,整数的值都不变。
      • 无符号 Uw2Uw+k(u)=B2Uw+k([0,,0k,Uw2B(u)])=uU_w2U_{w + k}(u) = B2U_{w + k}([\underbrace{0, \dots, 0}_{k}, U_w2B(u)]) = u
        • 直接在最高位前补 00
      • 补码 Tw2Tw+k(x)=B2Tw+k([xw1,,xw1k,Uw2B(x)])=xT_w2T_{w + k}(x) = B2T_{w + k}([\underbrace{x_{w - 1}, \dots, x_{w - 1}}_{k}, U_w2B(x) ]) = x
        • 在最高位前复制最高位,保证符号不变,这种机制叫符号扩展。
    • 截断
      • 基本原则:截断都在位级别保留最低的若干位,再重新解释为值。
      • 无符号 Uw+k2Uw(u)=B2Uw([uw1,,u0])=umod2wU_{w + k}2U_w(u) = B2U_w([u_{w - 1}, \dots, u_0]) = u \bmod 2^w
      • 补码 Tw+k2Tw(x)=B2Tw([xw1,,x0])T_{w + k}2T_w(x) = B2T_w([x_{w - 1}, \dots, x_0])
    • 加法
      • 基本原则:无符号和补码的加法在位级别上一样,均截断理论结果的位向量。
      • 无符号 UAddw(u,v)=(u+v)mod2wUAdd_w(u, v) = (u + v) \bmod 2^w
      • 补码 TAddw(x,y)=U2T((T2U(x)+T2U(y))mod2w)TAdd_w(x, y) = U2T((T2U(x) + T2U(y)) \bmod 2^w)
    • 乘法
      • 基本原则:无符号和补码的乘法法在位级别上一样,均截断理论结果的位向量。
      • 无符号 UMultw(u,v)=(uv)mod2wUMult_w(u, v) = (uv) \bmod 2^w
      • 补码 TMultw(x,y)=U2T((T2U(x)T2U(y))mod2w)TMult_w(x, y) = U2T((T2U(x) T2U(y)) \bmod 2^w)
      • 如果两个 ww 位整数相乘,则精确表示结果需要 2w2w 位。
    • 移位实现的乘除法
      • xx << k=x2kk = x 2^k
      • xx >> k=x2kk = \left\lfloor \dfrac{x}{2^k} \right\rfloor
      • 对于有符号数,实现向 00 取整除法:(x+(2k1))(x + (2^k - 1)) >> kk
  • 浮点数
    • 编码
      • IEEE 754 浮点数的二进制表示分为三部分:符号位 ss、阶码 ExpExp、尾数 FracFrac
        • 分别对应 (1)sM2E(-1)^s M 2^E 的符号位 ss、指数 EE、尾数 MM,但彼此不直接相等。
      • 精度:
        • 单精度:32 位,阶码用 8 位,尾数用 23 位。
        • 双精度:64 位,阶码用 11 位,尾数用 52 位。
      • Normalized Value:
        • ExpExp 为全 00 和 全 11 时,浮点数是 Normalized Value。
        • 阶码用偏置编码指数,E=ExpΔE = Exp - \Delta,其中 Δ=2k11\Delta = 2^{k - 1} - 1kk 为阶码长度。
        • 尾数表示为 M=1.[Frac]M = 1.[Frac][Frac][Frac] 直接使用尾数部分的二进制串。
      • Denormalized Value:
        • ExpExp 全为 00 时,浮点数是 Denormalized Value。
        • 指数规定为 E=1ΔE = 1 - \Delta
        • 尾数表示为 M=0.[Frac]M = 0.[Frac]
      • 无穷大:ExpExp 全为 11FracFrac 为全 00
      • NaN:ExpExp 全为 11FracFrac 不为全 00
    • 舍入
      • 四种舍入方式:
        • 向下舍入
        • 向上舍入
        • 向零舍入
        • 向偶数舍入:类似四舍五入,除了当被舍入的最高位为一半时,向被保留的最后一位的偶数方向舍入。
          • 1.23501.23501.24501.2450 都舍入为 1.241.24
      • 二进制下的向偶数舍入:
        • 仅当出现 ii.ff100\mathrm{i \cdots i}.\mathrm{f \cdots f}10 \cdots 0 时,需要特殊考虑舍入方向
        • 舍入向最后一个 f\mathrm{f}00 的方向。
    • 加法
      • 设浮点数 x=(1)sxMx2Ex,y=(1)syMy2Eyx = (-1)^{s_x} M_x 2^{E_x}, y = (-1)^{s_y} M_y 2^{E_y},且 Ex>EyE_x > E_y,则加法按照以下步骤:
        • MyM_yMxM_x 对齐,即 My2EyMy2ExEy2Ex=My2ExM_y 2^{E_y} \to \dfrac{M_y}{2^{E_x - E_y}} 2^{E_x} = M_y' 2^{E_x},结果的阶码则为 E=ExE = E_x
        • 相加 (1)sxMx(-1)^{s_x} M_x(1)syMy(-1)^{s_y} M_y',得到 MM
        • 根据 MM 修正结果:
          • 如果 M2M \ge 2,则 MM 右移除以 22,递增 EE
          • 如果 M<1M < 1,则 MM 左移 kk 位,EE 减去 kk,要求最后结果满足尾数的定点数格式。
        • 如果 EE 超出范围,则其饱和溢出,即最终结果表示为无穷大。
        • 舍入 MM 到合适的精度。
      • 代数性质:
        • 不满足结合律。
        • 基本可逆,除了无穷大和 NaN。
        • 基本满足单调性 ab    a+cb+ca \ge b \implies a + c \ge b + c,除了无穷大和 NaN。
    • 乘法
      • 设浮点数 x=(1)sxMx2Ex,y=(1)syMy2Eyx = (-1)^{s_x} M_x 2^{E_x}, y = (-1)^{s_y} M_y 2^{E_y},则乘法按照以下步骤:
        • 计算符号位 s=(sx+sy)mod2=sxsys = (s_x + s_y) \bmod 2 = s_x \oplus s_y
        • 计算指数 E=Ex+EyE = E_x + E_y
        • 计算尾数 M=MxMyM = M_x M_y
        • 根据 MM 修正结果、处理溢出和舍入,方法同加法。
      • 代数性质:
        • 不满足结合律。
        • 对加法不满足分配律。
        • 基本满足单调性 ab    acbc (c0)a \ge b \implies a c \ge b c\ (c \ge 0),除了无穷大和 NaN。