bitGateLab Digital · 学习
中文(简体)
打开模拟器

学习 › 第 6 讲

数制:二进制、八进制、十六进制与常用编码

阅读约 7 分钟 · bitGateLab 团队

数字电路只认识 0 和 1,而你却需要表示数量、正负号、显示器上的数字以及编码器的位置。本文将带你学习位置计数制的原理,在十进制、二进制、八进制和十六进制之间进行转换,用补码表示负数,并使用电子技术中两种非常常见的编码:BCD 码和格雷码。

位置计数制

在基数为 b 的位置计数制中,每一位数字都要乘以 b 的某次幂,幂次由它所在的位置决定,从最右边的 0 开始数。十进制数 347 等于 3·102 + 4·101 + 7·100。其他进制也是一样:

为避免混淆,用下标标明基数(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 转换成二进制、八进制和十六进制。

  1. 连续相除: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。
  2. 从下往上读余数:156 = 100111002。验证:128 + 16 + 8 + 4 = 156。
  3. 八进制:10 011 100 → 010 011 100 → 2 3 4。结果为 2348(2·64 + 3·8 + 4 = 156)。
  4. 十六进制:1001 1100 → 9 C。结果为 9C16(9·16 + 12 = 156)。

负数:补码

n 位的寄存器里没有地方放“负号”,所以要采用一种约定。几乎所有处理器采用的都是补码(即 2 的补码):最高位的位权为负,即 −2n−1,其余各位保持正的位权。8 位时的表示范围是 −128 到 +127;4 位时是 −8 到 +7。

求一个数的相反数的步骤:

  1. 写出该正数的全部二进制位。
  2. 把每一位取反(得到的是反码,即 1 的补码)。
  3. 加 1。

这样做的好处非常大:加法和减法用同一个加法器电路就能完成,不需要专门处理符号的逻辑。零只有一种表示(00000000),而且最高位直接表明这个数是否为负。

例 2:用 8 位表示 −45,并计算 25 + (−12)。

  1. 45 = 00101101。取反:11010010。加 1:11010011 = −45。
  2. 用位权验证:−128 + 64 + 16 + 2 + 1 = −45。
  3. 现在计算 25 + (−12)。25 = 00011001;12 = 00001100,取反得 11110011,加 1 得 11110100 = −12。
  4. 相加:00011001 + 11110100 = 1 00001101。从第 8 位产生的进位丢弃不要。
  5. 结果:00001101 = 13。正确。
溢出:如果两个同号的数相加,而结果的符号相反,说明结果超出了现有位数所能表示的范围。例如,在 8 位下 100 + 50 = 01100100 + 00110010 = 10010110,按补码解释它等于 −106,而不是 150。两个异号的数相加永远不会溢出。

BCD 码

在 BCD 码(二-十进制编码,这里指 8421 码)中,每一位十进制数字都单独用 4 位二进制表示。因此 395 写作 0011 1001 0101。这与把 395 转换成二进制(1100010112)不是一回事:BCD 码用的位数更多,但每一组都可以直接送到 7 段显示器的译码器,不需要做除法。1010 到 1111 这些代码在 BCD 码中是无效的;设计时,这些组合通常在卡诺图中当作无关项处理。

格雷码

在格雷码中,相邻两个值之间只有一位发生变化。在普通二进制中,从 7(0111)变到 8(1000)时四位同时变化;如果传感器恰好在跳变期间读数,就可能在一瞬间读到任何一个中间值。使用格雷码就不会出现这种错误,因此它被用于位置编码器、跨越不同时钟域的计数器,以及卡诺图的表头。

十进制二进制格雷码十进制二进制格雷码
000000000810001100
100010001910011101
2001000111010101111
3001100101110111110
4010001101211001010
5010101111311011011
6011001011411101001
7011101001511111000

例 3:把二进制 1011 转成格雷码,再转回来。

  1. 照抄第一位:1。
  2. 1 ⊕ 0 = 1;0 ⊕ 1 = 1;1 ⊕ 1 = 0。格雷码 = 1110。
  3. 转回来:照抄第一位,b3 = 1。然后 b2 = 1 ⊕ 1 = 0,b1 = 0 ⊕ 1 = 1,b0 = 1 ⊕ 0 = 1。二进制 = 1011。

在表中,十进制的 11 对应的格雷码是 1110:两者一致。

常见错误

在模拟器中试一试

只用几个输入和输出,你就能“实时”看到这些表示方法,并用 XOR 门验证到格雷码的转换。

  1. 放置四个输入作为 b3 到 b0 各位,并接上一个显示器或四个 LED 来查看数值。
  2. 添加三个 XOR 门:g2 = b3 ⊕ b2,g1 = b2 ⊕ b1,g0 = b1 ⊕ b0,并把 b3 直接连到 g3。
  3. 把输入从 0000 逐步变到 1111,观察输出:相邻两个值之间只有一个格雷码位发生变化。
  4. 生成电路的真值表,并与本文的表格比较。

练习

  1. 把 110101102 转换成十六进制和十进制。
    答案

    1101 0110 = D616 = 13·16 + 6 = 214。

  2. 把 200 转换成二进制和十六进制。
    答案

    200 = 128 + 64 + 8 = 110010002 = C816。

  3. 用 8 位补码表示 −100。
    答案

    100 = 01100100;取反得 10011011;加 1 得 10011100。验证:−128 + 16 + 8 + 4 = −100。

  4. 把十进制数 6 转换成 4 位格雷码,并把 BCD 码 0111 0010 转换成十进制。
    答案

    6 = 0110;格雷码:0,0 ⊕ 1 = 1,1 ⊕ 1 = 0,1 ⊕ 0 = 1 → 0101。BCD 码 0111 0010 表示 72。

想了解电路是如何对这些数做加减运算的,请继续学习二进制加法器。