软件设计师学习-码制

发布时间 2023-11-09 09:43:42作者: Glett

1. 原理

底层原理,经典计算机体系结构框架中只有加法器,因此,减法需要等价替换成加法。此处有两种思路:

  • 引入了负数的概念,将减法改写成加相反数
  • 考虑模运算和同余,可以将减数溢出为正数再相加

有此也就引出了反码和补码的概念。

1. 负数

负数和正数,需要用符号区分,因此牺牲一位作为符号位,将最高位定为符号位,1 表示负号,0 表示正号,此编码方式表示的机器数叫做原码。

2. 原码(True Form)

写出部分十进制数的原码,并进行一些运算:

码值 |  -3  |  -2  |  -1  |  -0  |  +0  |  +1  |  +2  |  +3  
原码 | 1011 | 1010 | 1001 | 1000 | 0000 | 0001 | 0010 | 0011 

+1 add +1 => 0001 add 0001 = 0010 => +2
+0 add -0 => 0000 add 1000 = 1000 => -0
+1 add -1 => 0001 add 1001 = 1010 => -2
+1 add -2 => 0001 add 1010 = 1011 => -3
-1 add -1 => 1001 add 1001 = 0010 => +2 (舍弃溢出位)

此处有几个问题:

  • 0 有正负两个
  • 负负相加时,结果异常
  • 正负相加时,结果异常

为了解决符号位问题,引入了反码和补码。

3. 反码(1’s Complement Code)

负数是一个正数的相反数,可以考虑用一个正数按位取反来表示负数。

码值 |  -3  |  -2  |  -1  |  -0  |  +0  |  +1  |  +2  |  +3  
原码 | 1011 | 1010 | 1001 | 1000 | 0000 | 0001 | 0010 | 0011 
反码 | 1100 | 1101 | 1110 | 1111 | 0000 | 0001 | 0010 | 0011 

+1 add +1 => 0001 add 0001 = 0010 => +2
+0 add -0 => 0000 add 1000 = 1000 => -0
+1 add -1 => 0001 add 1110 = 1111 => -0
+1 add -2 => 0001 add 1101 = 1110 => -1
-1 add -1 => 1110 add 1110 = 1100 => -3 (舍弃溢出位)

此处有几个问题:

  • 0 有正负两个
  • 负负相加时,结果异常

4. 补码(2’s Complement Code)

补码可以简单类别为常见的时钟,对于常见的范围是 0 到 12 的时钟而言,10 点减去 3 小时:

  • 10 - 3 = 7,即往回数到 7
  • 10 - 3 => 10 + (12 - 3) = 19 => 7,即往后数,超过 12 后,仍回到 7

超出 12 再减去 12 就是取模,7 和 19 就是同余数(7≡19(mod 12))。

对于 4bit 而言,最大容量为 24=16(即 1 0000),因此,负数可以重新表示为 1 0000 减去其绝对值:

码值 |  -3  |  -2  |  -1  |  -0  | + 0  |  +1  |  +2  |  +3  
原码 | 1011 | 1010 | 1001 | 1000 | 0000 | 0001 | 0010 | 0011 
反码 | 1100 | 1101 | 1110 | 1111 | 0000 | 0001 | 0010 | 0011 
补码 | 1101 | 1110 | 1111 |      | 0000 | 0001 | 0010 | 0011 

+1 add +1 => 0001 add 0001 = 0010 => +2
 0 add  0 => 0000 add 0000 = 0000 =>  0
+1 add -1 => 0001 add 1111 = 0000 =>  0 (舍弃溢出位)
+1 add -2 => 0001 add 1110 = 1111 => -1 
-1 add -1 => 1111 add 1111 = 1110 => -2 (舍弃溢出位)

5. 定义

若 X 是纯整数,则

码制

6. 反码和补码

反码和补码,从定义来看是没有关系的,但是由于 负数的反码+绝对值+1 = 10000 ,而 负数的补码+绝对值 = 10000,因此,负数的补码等于反码加一。


来自 Glett的码字间