课程笔记

2.3计算机中的二进制四则运算

阅读入口

定长容器与无符号加法

nn 位无符号整数把全部位宽用于表示大小:第 ii 位(最低位为第0位)的权是 2i2^i,因此它表示 00 到 2n−12^n-1 之间的全部整数,共 2n2^n 个不同的值。位权与进制记号的由来见进制转换。

位宽最大值常见对应
8位2552551字节
16位6553565535短整数
32位42949672954294967295单字(约42亿)

下文用固定位宽书写,(0101)2(0101)_2 表示4位二进制数 01010101;下标2是底数,不属于数值。

加法从最低位起逐位相加,逢二进一:

  • 1+1=(10)21+1=(10)_2:本位写0,向高位进1;
  • 1+1+1=(11)21+1+1=(11)_2:本位写1,向高位进1。

所以竖式中每一列的输入是“两个加数位 + 低位送来的进位”,输出是“本位和 + 向高位的进位”,一次最多进1。

本节从无符号加法起步,用位宽说明容器里的结果和真实值可以不同;后面的补码与浮点继续沿用定长字段。

补码

设有 nn 位二进制容器,整数 xx 的取值范围是 −2n−1≤x≤2n−1−1-2^{n-1}\le x\le 2^{n-1}-1。xx 的补码编码规定为:x≥0x\ge 0 时与 xx 的无符号二进制相同;x<0x<0 时取 2n+x2^n+x 的 nn 位二进制。因为 2n+x=2n−∣x∣2^n+x=2^n-|x|,负数的编码相当于从 2n2^n 中减去它的绝对值。

补码也可以按位权读:最高位的权是 −2n−1-2^{n-1},其余位的权仍是正的 2i2^i,即

x=−bn−12n−1+∑i=0n−2bi2i.x=-b_{n-1}2^{n-1}+\sum_{i=0}^{n-2}b_i2^i .

这解释了为什么最高位为1就代表负数,也说明最高位的权不是 −1-1 而是 −2n−1-2^{n-1},这是按位读补码时最容易出错的地方。非负数的补码与无符号编码完全一致;同一串位按哪种规则解释,取决于变量的类型,而不是位串本身。

位宽表示范围编码个数
8位−128∼127-128\sim 127256256
16位−32768∼32767-32768\sim 327676553665536
32位−2147483648∼2147483647-2147483648\sim 21474836472322^{32}

范围在负数一侧多一个数:−2n−1-2^{n-1} 有编码,而 +2n−1+2^{n-1} 没有。8位中1000 0000是 −128-128,1111 1111是 −1-1,0000 0000是0。无符号整数的位权与加法规则见二进制四则运算。

原码存在两个主要缺陷,补码与浮点的讨论从定长位串的解释规则出发。读定义时把注意力放在“同一串位按哪种规则解释”上。

浮点数的三段字段

二进制浮点数沿用科学计数法:先把数写成整数部分为一位的二进制小数,再乘以2的幂,即 ±(1.f)2×2e\pm(1.f)_2\times2^{e}。IEEE 754把符号、指数、尾数三段装进定长字段,其中指数存成偏移后的 E=e+127E=e+127(单精度),数值由下式还原:

V=(−1)S×(1.f)2×2E−127.V=(-1)^S\times(1.f)_2\times 2^{E-127}.

32位单精度的字段划分如下。

字段位数位置含义
符号 SS1第31位0为正,1为负
阶码 EE8第30~23位偏移后的指数,E=e+127E=e+127
尾数 ff23第22~0位小数点后的部分,隐含前导1

写成位串时依次是S EEEEEEEE FFF…F,阶码在前、尾数在后。记尾数位为 f1f2⋯f23f_1f_2\cdots f_{23}(f1f_1 紧接小数点),则

(1.f)2=1+∑i=123fi2−i,V=(−1)S(1+∑i=123fi2−i)2E−127.(1.f)_2=1+\sum_{i=1}^{23}f_i2^{-i},\qquad V=(-1)^S\left(1+\sum_{i=1}^{23}f_i2^{-i}\right)2^{E-127}.

这两个式子是换算的依据:先拆出三段,把阶码减127得到实际指数 ee,再把尾数按 2−1,2−2,…2^{-1},2^{-2},\dots 展开,最后加上隐含的1。

浮点部分把同一思路推到实数:符号、阶码、尾数各占定长字段,换算时按定义里的公式逐段还原。

学习安排

教材先用无符号加法建立“位宽决定范围”的观念,再说明乘法、除法只是移位后相加或相减;接着用原码的两个缺陷引出补码;最后把“符号 + 阶码 + 尾数”的思想推广到浮点数。三部分共用同一条主线:nn 位容器只有 2n2^n 个编码,所有规则都在回答这些编码分别代表什么数。

  • 加法、乘法先按竖式手算,把进位与部分积对齐写清楚,再去读知识点里的性质。
  • 补码先练8位正负转换,再练减法,最后单独做溢出判断。顺序颠倒容易把“进位”和“溢出”混为一谈。
  • 浮点数只要求会拆32位单精度并套数值公式;双精度记住位宽与偏移即可。

课程约定

  • 手算默认8位;题目给定4位或16位时以题目为准,位数不足在左侧补0。
  • 写补码按4位一组留空格,例如1111 1011;填空要求“只填0和1”时不写空格和下标。
  • 二进制竖式按位对齐,移位后的部分积直接写成移位后的数字,不再保留占位符。
  • 教材只在精度对比时提到双精度,其余浮点例子都用32位单精度。

易错点

  • 无符号加法丢掉最高位进位是回绕,属于溢出;补码减法丢掉进位却是正常结果。两处不要用同一句话记。
  • 补码的表示范围不对称:8位是 −128∼127-128\sim127,不是 −127∼127-127\sim127。
  • 判断补码溢出不能只看最高位有没有进位:8位中 127+1127+1 没有进位,结果却已经变成 −128-128。
  • 阶码是偏移后的值,套公式前必须先减127;尾数小数点前还有一个不存储的1。