2.2.7 截断数字
2.2.7 截断数字
假设我们不用额外的位来扩展一个数值,而是减少表示一个数字的位数。例如下面代码中这种情况:
int x = 53191;
short sx = (short) x; /* -12345 */
int y = sx; /* -12345 */当我们把 x 强制类型转换为 short 时,我们就将 32 位的 int 截断为了 16 位的 short int。就像前面所看到的,这个 16 位的位模式就是 -12 345 的补码表示。当我们把它强制类型转换回 int 时,符号扩展把高 16 位设置为 1,从而生成 -12 345 的 32 位补码表示。
当将一个 w 位的数 x = [xw-1, xw-2, ..., x0] 截断为一个 k 位数字时,我们会丢弃高 w-k 位,得到一个位向量 x' = [xk-1, xk-2, ..., x0]。截断一个数字可能会改变它的值,溢出的一种形式。对于一个无符号数,我们可以很容易得出其数值结果。
原理:截断无符号数
令 x 等于位向量 [xw-1, xw-2, ..., x0],而 x' 是将其截断为 k 位的结果:[xk-1, xk-2, ..., x0]。令 x = B2Uw(x),x' = B2Uk(x')。则 x' = x mod 2k。
该原理背后的直觉就是所有被截去的位其权重形式都为 2i,其中 i ≥ k,因此,每一个权在取模操作下结果都为零。可用如下推导表示:

补码截断也具有相似的属性,只不过要将最高位转换为符号位:
原理:截断补码数值
令 x 等于位向量 [xw-1, xw-2, ..., x0],而 x' 是将其截断为 k 位的结果:[xk-1, xk-2, ..., x0]。令 x = B2Uw(x),x' = B2Tk(x')。则 x' = U2Tk(x mod 2k)。
在这个公式中,x mod 2k 将是 0 到 2k-1 之间的一个数。对其应用函数 U2Tk 产生的效果是把最高有效位 xk-1 的权重从 2k-1 转变为 -2k-1。举例来看,将数值 x = 53 191 从 int 转换为 short。由于 216 = 65 536 ≥ x,我们有 x mod 216 = x。但是,当我们把这个数转换为 16 位的补码时,我们得到 x' = 53 191 - 65 536 = -12 345。

总而言之,无符号数的截断结果是公式(2.9),而补码数字的截断结果是公式(2.10):
B2Uk([xk-1, xk-2, ..., x0]) = B2Uw([xw-1, xw-2, ..., x0]) mod 2k (2.9)
B2Tk([xk-1, xk-2, ..., x0]) = U2Tk(B2Uw([xw-1, xw-2, ..., x0]) mod 2k) (2.10)
练习题 2.24 假设将一个 4 位数值(用十六进制数字 0~F 表示)截断到一个 3 位数值(用十六进制数字 0~7 表示)。填写下表,根据那些位模式的无符号和补码解释,说明这种截断对某些情况的结果。
| 十六进制:原始值 | 十六进制:截断值 | 无符号:原始值 | 无符号:截断值 | 补码:原始值 | 补码:截断值 |
|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | ||
| 2 | 2 | 2 | 2 | ||
| 9 | 1 | 9 | -7 | ||
| B | 3 | 11 | -5 | ||
| F | 7 | 15 | -1 |
解释如何将等式(2.9)和等式(2.10)应用到这些示例上。