原码、反码、补码、移码 总结​

Xin-dudu 发布于 2025-09-18 79 次阅读


先记个基础:符号位和数值位​

计算机用二进制存整数,要区分正负,就规定了 “符号位 + 数值位”:​

  • 最高位(最左边)是符号位:0 = 正数,1 = 负数​
  • 剩下的是数值位:存数字的绝对值(原码里是这样,后面补码反码会变)​
  • 后面全用 8 位二进制举例(1 位符号位 + 7 位数值位),好算也好记​

​​

一、原码:最直观但问题最多的编码​

1. 怎么表示?​

  • 正数:符号位 0 + 数值的二进制(比如 + 5 就是 00000101,0 是符号位,0000101 是 5 的二进制)​
  • 负数:符号位 1 + 数值的二进制(比如 - 5 就是 10000101,1 是符号位,后面跟 5 的二进制)​

2. 举几个例子(8 位)​

十进制​原码​备注​
+0​00000000​符号位 0,数值位全 0​
-0​10000000​符号位 1,数值位全 0​
+127​01111111​7 位数值位最大就是 1111111​
-127​11111111​符号位 1 + 数值位 1111111​
+3​00000011​简单数方便后面算运算​
-3​10000011​同上​

3. 致命问题(为啥现在不用)​

  • 0 有两个表示:+0(00000000)和 - 0(10000000),纯属浪费空间​
  • 加减法不能一起算:计算机得单独设计加法器和减法器,麻烦​
  • 比如算 5-3,按道理是 5+(-3),用原码算:​

00000101(+5) + 10000011(-3)= 10001000(对应十进制 - 8),明显错了!​

  • 加法还行,减法一塌糊涂,所以原码被淘汰了​

​​

二、反码:过渡用的 “半成品”​

1. 怎么表示?​

  • 正数:和原码一样(符号位 0 + 数值位,不变)​
  • 负数:符号位不变,数值位按位取反(0 变 1,1 变 0)​

2. 举例子(对比原码)​

十进制​原码​反码​计算过程(负数)​
+0​00000000​00000000​正数反码 = 原码​
-0​10000000​11111111​符号位 1 不变,数值位 0000000 取反成 1111111​
+5​00000101​00000101​正数反码 = 原码​
-5​10000101​11111010​符号位 1 不变,数值位 0000101 取反成 1111010​
-3​10000011​11111100​符号位 1 不变,数值位 0000011 取反成 1111100​

3. 反码的唯一作用:试着统一加减法​

反码的思路是:把减法变成 “加负数的反码”,让计算机只用加法器就行​

  • 还是算 5-3=5+(-3):​

5 的反码(00000101) + (-3) 的反码(11111100)= 100000001​

因为是 8 位二进制,超出 8 位的 “1” 直接扔掉,剩下 00000001(对应十进制 1),对了!​

  • 再算 - 5 + (-3):​

-5 的反码(11111010) + (-3) 的反码(11111100)= 11110110(舍弃进位 1 后)​

这时候要注意:如果相加后没有进位(或者说结果是负数),需要把数值位再取反一次才是最终值​

符号位 1 不变,数值位 1110110 取反成 0001001,结果是 10001001(对应十进制 - 9),对了!​

4. 为啥是过渡品?​

  • 0 的二义性还在:+0(00000000)和 - 0(11111111)还是两个,没解决​
  • 有进位和没进位要分情况处理:刚才算 - 5+(-3) 时,得二次取反,计算机处理起来麻烦,不如补码省心​

三、补码:现在计算机真正在用的编码​

补码是反码的升级版,解决了所有遗留问题,现在电脑里存整数、算加减,全靠它!​

1. 怎么表示?​

  • 正数:和原码、反码都一样(符号位 0 + 数值位,不变)​
  • 负数:符号位不变,数值位取反后再加 1(简单说就是 “反码 + 1”)​

2. 举例子(对比原码、反码)​

十进制​原码​反码​补码​计算过程(负数)​
+0​00000000​00000000​00000000​正数补码 = 原码​
-0​10000000​11111111​00000000​反码 11111111 +1 = 100000000,舍弃进位 1,剩 00000000​
+5​00000101​00000101​00000101​正数补码 = 原码​
-5​10000101​11111010​11111011​反码 11111010 +1 = 11111011​
-3​10000011​11111100​11111101​反码 11111100 +1 = 11111101​
-128​没有(原码最大负是 - 127)​没有​10000000​补码独有的,用 - 0 空出来的编码表示​

3. 补码的核心优点(为啥能成为标准)​

(1)0 终于只有一种表示了!​

这是最关键的改进,之前原码、反码的坑终于填上了:​

  • 原码里 - 0 是 10000000,补码计算 - 0 时,反码 11111111 +1 = 100000000,超出 8 位的进位扔掉,结果和 + 0 的补码一样(00000000)​
  • 空出来的 10000000 这个编码,正好用来表示 - 128(8 位补码范围变成 - 128~+127,比原码多一个数,不浪费空间)​

(2)加减法彻底统一,不用分情况!​

不管正数加负数、负数加负数,直接用补码相加,扔掉超出的进位,结果就是对的,不用二次处理:​

  • 例 1:5-3=5+(-3)​

5 的补码(00000101) + (-3) 的补码(11111101)= 100000010​

舍弃进位 1,剩 00000010(十进制 2),正确!​

  • 例 2:-5 + (-3)​

-5 的补码(11111011) + (-3) 的补码(11111101)= 11111000(舍弃进位 1 后)​

11111000 对应十进制 - 8,正确!​

  • 例 3:-128 + 127​

-128 的补码(10000000) + 127 的补码(01111111)= 11111111(十进制 - 1),正确!​

(3)计算机硬件简单​

只用设计一个加法器,就能算所有加减,不用搞减法器,省成本还高效​

​​

四、移码:专门用来比较大小的编码​

移码不用来存数、算加减,就一个用途:给浮点数的 “阶码”(指数部分)用,方便比较两个浮点数的大小​

1. 怎么表示?​

最简单的记法:移码 = 补码的符号位取反(数值位完全不变)​

  • 也可以用公式:移码 = 十进制数 + 偏移量(偏移量是 2^(n-1),n 是编码位数,8 位的话就是 128)​

2. 举例子(8 位,对比补码)​

十进制​补码​移码​公式计算(数 + 128)​
-128​10000000​00000000​-128 + 128 = 0 → 00000000​
-5​11111011​01111011​-5 + 128 = 123 → 01111011​
0​00000000​10000000​0 + 128 = 128 → 10000000​
+5​00000101​10000101​5 + 128 = 133 → 10000101​
+127​01111111​11111111​127 + 128 = 255 → 11111111​

3. 核心作用:快速比大小​

移码把有符号数变成了无符号数,所以移码的大小关系和原数完全一致,直接比二进制就行:​

  • 比如比较 - 5 和 + 5:​

-5 的移码是 01111011(对应无符号数 123),+5 的移码是 10000101(对应 133)​

123 < 133 → 所以 - 5 < +5,一眼就看出来了​

  • 浮点数比大小,核心就是比阶码,用移码表示阶码,计算机不用处理符号位,直接按无符号数比,快多了​

五、关键问题总结​

  1. 为啥原码 0 有两种,补码只有一种?
  • 原码:符号位和数值位分开定义,+0 是 0+0,-0 是 1+0,自然两个​
  • 补码:-0 的反码 + 1 后,超出位数的进位被扔了,结果和 + 0 一样,所以合并成一个​
  1. 反码到底有啥用?
  • 过渡用的,帮着理解补码的由来,它尝试解决原码的运算问题,但没解决干净,最后被补码取代,现在计算机里基本不用了​
  1. 补码为啥是 “取反加 1”?
  • 数学上的 “模运算”,8 位二进制的模是 256,减去一个数 = 加上(256 - 这个数)​
  • “取反” 相当于 255 - 这个数,再加 1 就是 256 - 这个数,正好把减法变成加法,方便计算机计算​
  1. 四个编码的核心用途?
  • 原码:直观但没用了​
  • 反码:过渡,理解补码用​
  • 补码:存整数、算加减,现在的主力​
  • 移码:浮点数阶码,方便比大小​
此作者没有提供个人介绍。
最后更新于 2025-09-18