学习 › 第 6 讲
数制:二进制、八进制、十六进制与常用编码
阅读约 7 分钟 · bitGateLab 团队
数字电路只认识 0 和 1,而你却需要表示数量、正负号、显示器上的数字以及编码器的位置。本文将带你学习位置计数制的原理,在十进制、二进制、八进制和十六进制之间进行转换,用补码表示负数,并使用电子技术中两种非常常见的编码:BCD 码和格雷码。
位置计数制
在基数为 b 的位置计数制中,每一位数字都要乘以 b 的某次幂,幂次由它所在的位置决定,从最右边的 0 开始数。十进制数 347 等于 3·102 + 4·101 + 7·100。其他进制也是一样:
- 二进制(基数为 2):数字为 0 和 1,称为位(bit)。位权为 1、2、4、8、16、32、64、128……
- 八进制(基数为 8):数字为 0 到 7。每一位八进制数字相当于 3 位二进制。
- 十六进制(基数为 16):数字为 0 到 9 和 A 到 F(A = 10,B = 11,C = 12,D = 13,E = 14,F = 15)。每一位十六进制数字相当于 4 位二进制。
为避免混淆,用下标标明基数(10102、178、3F16),或者使用 0b、0x 这样的前缀。
进制之间的转换
任意进制转十进制
把每一位数字乘以它的位权,然后相加。例如,2F316 = 2·256 + 15·16 + 3·1 = 512 + 240 + 3 = 755。
十进制转二进制
反复除以 2 并记下余数;二进制数要从下往上读(最后得到的余数是最高位)。另一种方法是一次又一次地减去不超过当前数的最大的 2 的幂。
二进制、八进制与十六进制之间
由于 8 = 23,16 = 24,不必经过十进制:从右边开始,把二进制位 3 位 3 位地(八进制)或 4 位 4 位地(十六进制)分组,必要时在左边补零。
例 1:把 156 转换成二进制、八进制和十六进制。
- 连续相除:156/2 = 78 余 0;78/2 = 39 余 0;39/2 = 19 余 1;19/2 = 9 余 1;9/2 = 4 余 1;4/2 = 2 余 0;2/2 = 1 余 0;1/2 = 0 余 1。
- 从下往上读余数:156 = 100111002。验证:128 + 16 + 8 + 4 = 156。
- 八进制:10 011 100 → 010 011 100 → 2 3 4。结果为 2348(2·64 + 3·8 + 4 = 156)。
- 十六进制:1001 1100 → 9 C。结果为 9C16(9·16 + 12 = 156)。
负数:补码
n 位的寄存器里没有地方放“负号”,所以要采用一种约定。几乎所有处理器采用的都是补码(即 2 的补码):最高位的位权为负,即 −2n−1,其余各位保持正的位权。8 位时的表示范围是 −128 到 +127;4 位时是 −8 到 +7。
求一个数的相反数的步骤:
- 写出该正数的全部二进制位。
- 把每一位取反(得到的是反码,即 1 的补码)。
- 加 1。
这样做的好处非常大:加法和减法用同一个加法器电路就能完成,不需要专门处理符号的逻辑。零只有一种表示(00000000),而且最高位直接表明这个数是否为负。
例 2:用 8 位表示 −45,并计算 25 + (−12)。
- 45 = 00101101。取反:11010010。加 1:11010011 = −45。
- 用位权验证:−128 + 64 + 16 + 2 + 1 = −45。
- 现在计算 25 + (−12)。25 = 00011001;12 = 00001100,取反得 11110011,加 1 得 11110100 = −12。
- 相加:00011001 + 11110100 = 1 00001101。从第 8 位产生的进位丢弃不要。
- 结果:00001101 = 13。正确。
BCD 码
在 BCD 码(二-十进制编码,这里指 8421 码)中,每一位十进制数字都单独用 4 位二进制表示。因此 395 写作 0011 1001 0101。这与把 395 转换成二进制(1100010112)不是一回事:BCD 码用的位数更多,但每一组都可以直接送到 7 段显示器的译码器,不需要做除法。1010 到 1111 这些代码在 BCD 码中是无效的;设计时,这些组合通常在卡诺图中当作无关项处理。
格雷码
在格雷码中,相邻两个值之间只有一位发生变化。在普通二进制中,从 7(0111)变到 8(1000)时四位同时变化;如果传感器恰好在跳变期间读数,就可能在一瞬间读到任何一个中间值。使用格雷码就不会出现这种错误,因此它被用于位置编码器、跨越不同时钟域的计数器,以及卡诺图的表头。
- 二进制转格雷码:最高位照抄;其后的每一位都是对应的二进制位与它左边那个二进制位的 XOR。写成公式就是 g = b ⊕(b 右移一位)。
- 格雷码转二进制:最高位照抄;其后的每一个二进制位都是刚求出的二进制位与该位置上格雷码位的 XOR。
| 十进制 | 二进制 | 格雷码 | 十进制 | 二进制 | 格雷码 |
|---|---|---|---|---|---|
| 0 | 0000 | 0000 | 8 | 1000 | 1100 |
| 1 | 0001 | 0001 | 9 | 1001 | 1101 |
| 2 | 0010 | 0011 | 10 | 1010 | 1111 |
| 3 | 0011 | 0010 | 11 | 1011 | 1110 |
| 4 | 0100 | 0110 | 12 | 1100 | 1010 |
| 5 | 0101 | 0111 | 13 | 1101 | 1011 |
| 6 | 0110 | 0101 | 14 | 1110 | 1001 |
| 7 | 0111 | 0100 | 15 | 1111 | 1000 |
例 3:把二进制 1011 转成格雷码,再转回来。
- 照抄第一位:1。
- 1 ⊕ 0 = 1;0 ⊕ 1 = 1;1 ⊕ 1 = 0。格雷码 = 1110。
- 转回来:照抄第一位,b3 = 1。然后 b2 = 1 ⊕ 1 = 0,b1 = 0 ⊕ 1 = 1,b0 = 1 ⊕ 0 = 1。二进制 = 1011。
在表中,十进制的 11 对应的格雷码是 1110:两者一致。
常见错误
- 转换成八进制或十六进制时从左边开始分组。分组永远要从最低位开始。
- 忘记补码的“+1”。只取反得到的是反码,它有两个零,表示范围也不同。
- 寄存器存放的是有符号数时,把 11010011 当成 211。同一种位模式,按无符号数是 211,按有符号数是 −45:取决于采用哪种约定。
- 把 BCD 码和二进制混为一谈。25 的 BCD 码是 0010 0101,而它的二进制是 11001。
- 格雷码转二进制时,用相邻的格雷码位而不是刚算出的二进制位去做 XOR。
在模拟器中试一试
只用几个输入和输出,你就能“实时”看到这些表示方法,并用 XOR 门验证到格雷码的转换。
- 放置四个输入作为 b3 到 b0 各位,并接上一个显示器或四个 LED 来查看数值。
- 添加三个 XOR 门:g2 = b3 ⊕ b2,g1 = b2 ⊕ b1,g0 = b1 ⊕ b0,并把 b3 直接连到 g3。
- 把输入从 0000 逐步变到 1111,观察输出:相邻两个值之间只有一个格雷码位发生变化。
- 生成电路的真值表,并与本文的表格比较。
练习
- 把 110101102 转换成十六进制和十进制。
答案
1101 0110 = D616 = 13·16 + 6 = 214。
- 把 200 转换成二进制和十六进制。
答案
200 = 128 + 64 + 8 = 110010002 = C816。
- 用 8 位补码表示 −100。
答案
100 = 01100100;取反得 10011011;加 1 得 10011100。验证:−128 + 16 + 8 + 4 = −100。
- 把十进制数 6 转换成 4 位格雷码,并把 BCD 码 0111 0010 转换成十进制。
答案
6 = 0110;格雷码:0,0 ⊕ 1 = 1,1 ⊕ 1 = 0,1 ⊕ 0 = 1 → 0101。BCD 码 0111 0010 表示 72。
想了解电路是如何对这些数做加减运算的,请继续学习二进制加法器。