Featured image of post lecture03 Bits,Bytes and Integer cout

lecture03 Bits,Bytes and Integer cout

CMU 15-213 lecture3

加法

无符号加法

无符号的加法很简单,和二进制加法一样,只不过要把overflow的删除,并且把结果取模即可

可视化整数加法图

可视化无符号加法图

检测无符号数中加法的溢出

令 $s = U +_w^u V$ 为无符号整数 $U$ 和 $V$ 的和,那么当且仅当 $s < U$(或等价的 $s < V$)时产生溢出,这是因为:

$$ \begin{aligned} s &= U + V - 2^w < U \\ s &= U + V - 2^w < V \end{aligned} $$

补码加法

![](截屏2025-09-28 15.57.52.jpg)

对满足 $-2^{w-1} \leq x$,$y \leq 2^{w-1}-1$ 的整数 $x$ 和 $y$,有:

$$ x +_w^t y = \begin{cases} x + y - 2^w, & 2^{w-1} \leq x + y \quad \text{正溢出} \\ x + y, & -2^{w-1} \leq x + y < 2^{w-1} \quad \text{正常} \\ x + y + 2^w, & x + y < -2^{w-1} \quad \text{负溢出} \end{cases} $$

两个数的$w$位补码之和与无符号之和有完全相同的位级表示

利用左移做乘法

  • 大多数机器中左移比乘法快
    • 编译器会自动生成这样的代码

方法的证明:

假设 $x$ 的 $w$ 位二进制表示为 $\left[x_{w-1}, x_{w-2}, \cdots, x_{0}\right]$,那么 $\left[x_{w-1}, x_{w-2}, \cdots, x_{0}, 0, \cdots, 0\right]$ 给出了 $x2^k$ 的 $w+k$ 位二进制表示:

$$ \begin{aligned} B2U_{w+k}\left(\left[x_{w-1}, x_{w-2}, \cdots, x_{0}, 0, \cdots, 0\right]\right) &= \sum_{i=0}^{w-1} x_{i} 2^{i+k} \\ &= \left[\sum_{i=0}^{w-1} x_{i} 2^{i}\right] \cdot 2^{k} \\ &= x 2^{k} \end{aligned} $$

对于固定长度的表示,高 $k$ 位被丢弃,左移 $k$ 位的二进制表示为

$$ \left[x_{w-k-1}, x_{w-k-2}, \cdots, x_{0}, 0, \cdots, 0\right] $$

所以

$$ \begin{aligned} B2U_{w}\left(\left[x_{w-k-1}, x_{w-k-2}, \cdots, x_{0}, 0, \cdots, 0\right]\right) &= \sum_{i=0}^{w-k-1} x_{i} 2^{i+k} \\ &= \left[\sum_{i=0}^{w-k-1} x_{i} 2^{i}\right] \cdot 2^{k} \\ &= \left[\sum_{i=0}^{w-1} x_{i} 2^{i}\right] \cdot 2^{k} \mod 2^w \\ &= x2^k \mod 2^w \end{aligned} $$

所以对于无符号整数

$$ B2U_{w}\left(\left[x_{w-k-1}, x_{w-k-2}, \cdots, x_{0}, 0, \cdots, 0\right]\right) = \text{UMult}_w(x,2^k) $$

对于有符号整数,利用

$$ \text{TMult}_w(u,v) = U2T_w((u \cdot v) \mod 2^w) $$

可以得到相同的结果。

一般情形

现在考虑一般的情形,假设我们需要计算 $u \times K$,其中 $K$ 为常数,将 $K$ 表达为一组 $0$ 和 $1$ 交替的序列

$$ [(0 \cdots 0)(1 \cdots 1)(0 \cdots 0) \cdots (1 \cdots 1)] $$

考虑一组从位置 $n$ 到位置 $m$ 的连续 $1$,那么可以用如下方式计算这部分的对于乘积的影响:

$$ \begin{aligned} &(x << n) + (x << (n-1)) + \cdots + (x << m) \\ &(x << (n+1)) - (x << m) \end{aligned} $$

移位操作和二进制乘除法的联系

使用移位操作代替除以 2 的幂(无符号)

  • $u » k$ 给出 $\lfloor u / 2^{k} \rfloor$
  • 使用逻辑移位

证明:

假设 $x$ 的 $w$ 位二进制表示为 $\left[x_{w-1}, x_{w-2}, \cdots, x_{0}\right]$,右移 $k$ 位的二进制表示为 $\left[0, \cdots, 0, x_{w-1}, x_{w-2}, \cdots, x_{k}\right]$

$$ \begin{aligned} B2U_w(\left[0, \cdots, 0, x_{w-1}, x_{w-2}, \cdots, x_{k}\right]) &= \sum_{i=0}^{w-k-1} x_{i+k} 2^{i} \\ B2U_{w}\left(\left[x_{w-1}, x_{w-2}, \cdots, x_{0}\right]\right) &= \sum_{i=0}^{w-1} x_{i} 2^{i} \\ &= 2^k \sum_{i=0}^{w-k-1} x_{i+k} 2^{i} + \sum_{i=0}^{k-1} x_{i} 2^{i} \\ &= 2^k B2U_w(\left[0, \cdots, 0, x_{w-1}, x_{w-2}, \cdots, x_{k}\right]) + \sum_{i=0}^{k-1} x_{i} 2^{i} \end{aligned} $$

所以

$$ \lfloor x / 2^{k} \rfloor = x >> k $$

使用移位操作代替除以 2 的幂(有符号)

  • $u » k$ 给出 $\lfloor u / 2^{k} \rfloor$
  • 使用算数移位

当 $u > 0$ 时上述方法和无符号情形一致,但是当 $u < 0$ 时则会产生有问题的结果,例如取 $u = -12340$:

考虑 $k=4,8$ 时的结果,在 C 语言中实际结果为 $-771$ 和 $-48$,之所以和 C 语言中的结果不同,是因为上述算法朝着离 $0$ 更远的方向舍入,所以当 $u < 0$ 时要向上舍入,达到上述效果利用如下事实即可

$$ \lceil x / y \rceil = \lfloor (x + y - 1) / y \rfloor $$

Unsigned

  • 必须做一个明确的分配而不是暗示

    • 容易犯错误,例如下面的代码会出现无限循环

      1
      2
      3
      
      unsigend i;
      for(i = cnt - 2;i >= 2;i --)
      	a[i] += a[i + 1];
      
    • 可能会变的很诡异

      1
      2
      3
      
      #define DELTA sizeof(int)//默认int的size是一个unsigned的size_t
      int i;
      for(i = CNT;i - DELTA >= 0;i -=DELTA)//和上面的代码出现一样的问题
      
  • 正确的代码如下

1
2
3
size_t i;
for (i = cnt-2; i < cnt; i--)
	a[i] += a[i+1];

什么时候用无符号整数

  • 执行模块化算术时使用

    • 多精度算术
  • 在使用位表示集时使用

    • 逻辑右移,无符号扩展

(最好不要用unsigned)

内存中数字的一些底层表示

Word Size

  • 硬件本身并不一定定义字长大小

  • 任何给定的计算机都具有字长

  • 直到现在,大部份机器都采用32 bits(4 bytes)作为字长

    • 地址限制为4 GB($2^{32}$bytes)
  • 越来越多机器具有64位字长

  • 机器仍然支持多种数据格式

    • 字长的分数或整数倍
    • 但总是整数比特

比特顺序

分为大端法和小端法

  • Example
    • 变量x的value是0x01234567
    • 地址是0x100

使用 Hugo 构建
主题 StackJimmy 设计