原码、反码、补码

原码、补码、反码是计算机中最基础的知识,但一直没熟练掌握,经常忘,这里做个记录。

原码

最高位是符号位,其余位用来表示这个数的绝对值。
例如 在32位数中:

 +1的原码是0000,0001;
 +5的原码是0000,0101;
 -17的原码是1001,0001;

如果这个世界只有正数,那么我们只需要原码就够了,但还有负数…

例如:

-3(1000,0011)+3(0000,0011)= -6(1000,0110)

因此,原码会带来两个问题

  • 负数或减法运算会出现错误
  • 0有两种表示方式 +0(0000,0000) 和 -0(1000,0000)

反码

正数反码就是原码,负数符号位不变,其余位取反
我们尝试用反码来计算减法:

-3(1111,1100)+3(0000,0011)= -0(1111,1111)

乍一看计算结果好像是正确的,那我们再试两个:

4(0000,0100)-9(1111,0110)= -5(1111,1010)
-28(1110,0011)+8(0000,1000)= -20(1110,1011)

也是正确的,再试两个:

4(0000,0100)-3(1111,1100)= 0(1,0000,0000)舍去高位变成0
17(0001,0001)-6(1111,1001)= 10(1,0000,1010)舍去高位变成10

在这两个例子都是大正数加上一个小负数,都出现了溢出,舍去最高位后都不是正确的答案。

反码也还是存在一些问题

  • 部分运算还是不正确的,绝对值相同的正数和负数相加是正确的
  • 0还是有两种表示方式,+0(0000,0000) 和 -0(1111,1111)

补码

正数的补码就是原码,负数的补码是反码+1

  之前说过,反码的”0“是有两种表示方式,+0(0000,0000) 和 -0(1111,1111)。

  但在补码中,”+0“的补码还是”0000,0000“,计算”-0“的补码,反码+1,变成了”1,0000,0000”,舍去最高位也变成了”0000,0000” 。

  因此补码中的”0“只有一种表达方式—— “0000,0000”

  同样,不会出现计算错误的情况:

4(0000,0100)-3(1111,1101)= 1(1,0000,0001)舍去高位变成1
17(0001,0001)-6(1111,1010)= 11(1,0000,1011)舍去高位变成11

反码和补码都是为了解决负数问题而出现的,所以正数的反码和补码都是原码。####

为什么负数总比正数多一个?####

  理论上,8位数,用补码表示的范围是 1111,1111 ~ 0111,111 ,即 -127,-126,-125 ….-1,-2,-0,+0,1,2 …. 126,127 去掉”-0” 就可以了。由于在补码中,没有反码可以通过+1变成”1000,0000”,所以人为规定”1000,0000”为”-128”,这也是为什么负数比正数多一个的原因。