当前位置: 首页 > news >正文

计算机组成与体系结构:补码数制一(Complementary Number Systems)

目录

为什么需要补码数制?

什么是原码?

什么是反码?

 补码为什么被设计出来?

 补码是怎么做出来的?

什么是模运算?

为什么所有运算其实都是“模 2ⁿ”的运算? 

1️⃣ 什么是补码?

2️⃣怎么快速求出 2ⁿ - x 呢?

为啥加这个补码就能完成减法?


为什么需要补码数制?

你可以想象一下,如果我们把一台计算机看作一个只会处理“二进制加法”的机器人,那它就不会直接做“减法”或“处理正负号”。那我们该怎么告诉这个机器人该怎么做呢?

这就需要一种“编码方法”,能:

  • 表示正数和负数 

  • 让机器人只用加法就能完成加法和减法 

  • 还不容易出错 

这种方法,就是我们今天要学的 —— 补码数制(Two's Complement System)。


 我们学习补码数制的核心原因,是为了解决有符号数(Signed Numbers)在计算机中进行加减运算时所面临的表示和运算复杂性问题。

我们人类很容易分辨 +5 和 -5。可计算机内部只认得0 和 1,它怎么知道哪个数是正的、哪个是负的?

早期人们想了三种办法来解决:

方法举例(以+5为例)举例(以-5为例)存在问题
原码(Sign-Magnitude)0000010110000101有两个“0”(+0和-0),而且加减复杂
反码(Ones' Complement)0000010111111010仍然有两个“0”,还要处理进位问题
补码(Two's Complement)0000010111111011✅ 只有一个“0”,加法也能做减法!

所以,“补码”是三种方法中最优秀、最实用的一种。

什么是原码?

原码的思想非常简单:

最前面一位表示符号(Sign Bit),后面剩下的表示“数值大小”(Magnitude)

数值原码(二进制)说明
+500000101符号位是 0,表示正数
-510000101符号位是 1,表示负数,数值还是 5

✅ 特点:

  • 人类容易理解(我们习惯于“+/-”)

  • 正数和负数的数值部分是一样的

❌ 缺点:

  • 存在两个“0”:+0 是 00000000,-0 是 10000000

  • 加法、减法无法统一,只能通过判断符号、分情况计算

  • 实现麻烦,尤其在硬件上(要分符号处理)

什么是反码?

 定义:

正数的反码 = 自身的二进制(和原码一样)
负数的反码 = 原码按位取反(0变1,1变0)

为什么要先发明反码?

反码是人类“用取反方式近似负数”的第一步尝试,但它仍然不完美(有两个零、进位问题),于是才改进成“补码”。

原码(Sign-Magnitude):

  • 虽然正负都能表示,但加减法必须判断符号、做特殊处理,复杂 ❌

所以人们想:

能不能想个方法,不管是加正数还是负数,都用一个“普通的二进制加法器”来搞定?

于是就有了“反码”:

负数 = 把正数按位取反

✅ 反码的特点:

  • 对正数:反码和原码相同

  • 对负数:按位取反

  • 存在两个零:

    • 00000000(+0)

    • 11111111(-0)

❌ 反码的加法有问题:

举个例子:

+5 = 00000101  
-5 = 11111010(反码)  
相加:00000101 + 11111010 = 11111111 (这是 -0)

如果你想得到 0,你得“把最左边的进位再加回来”,这叫“尾进位回加(End-around carry)”。

这很麻烦,于是人们就设计了“补码”来解决这个问题。

补码和反码的关系:

补码 = 反码 + 1

🔍 本质原因:数学中的“模运算”告诉我们(下面会提到):

 而如果你从反码的角度来看:

(因为 ~x 就是所有位取反,相当于 2ⁿ-1 - x)

那么:

 ✅ 正好得到了我们需要的补码形式!

所以“补码 = 反码 + 1”并不是人随便凑出来的,而是来自于数学上:

想要表达 -x = 2^n - x,而又不想每次手算 2^n - x,于是用“取反 + 1”作为快速计算方式。


 补码为什么被设计出来?

补码被设计出来,主要是为了解决以下两个问题:

✨ 问题1:怎么用同一个计算器完成加法和减法?

计算机的电路(比如加法器)本来只会做二进制加法(Binary Addition)。但现在你要让它“减”怎么办?

答案是:把“减法”变成“加法”!

7 - 5 = 7 + (-5)

如果你能找到一种方法,把 -5 表示成一种“特别的加数”,那减法也就变成加法了。

补码就是用来表示“负数”的那种特别编码方法,这样计算机只需要一个“加法器”就够了。

✨ 问题2:怎么让表示方式更统一、逻辑更清晰?

在原码或反码表示中:

  • 有两个零(+0 和 -0)

  • 比较、判断、计算都麻烦

但补码:

  • 只用 00000000 表示 0

  • 正数不用变,负数用一种规律取反加一的方式表示

  • 数值范围对称,逻辑自然,硬件也更容易做出来


 补码是怎么做出来的?

原理背后:模(modulo)运算思想

什么是模运算?

🎯 定义:

模运算就是只保留“除以某个数后的余数”,也叫“取模”。

用数学语言说就是:

表达式结果
7 mod 52
15 mod 87
-1 mod 87 (因为 -1 + 8 = 7)

模运算在补码系统中的应用

计算机中 n 位能表示的数有限,比如 8 位可以表示的总数是:

2 ^8 = 256

所以,在计算机里,所有运算其实都是“模 256”的运算,即:

为什么所有运算其实都是“模 2ⁿ”的运算? 

💻 原因是:计算机能处理的数据是“位数有限”的

  • 一个 8 位的 CPU 加法器,只能表示和处理 8 个比特(bit)

  • 8 位能表示的范围是:从 0 到 255,总共 2⁸ = 256 个数

所以一切加法、减法、运算,最终都要“截断”到这 256 个数里。

 举个例子说明“模”的意义:

255 + 1 = 256 → 结果是 0(因为超出了范围,回到起点)

是不是像时钟?

  • 12 点 + 3 小时 = 3 点(模 12)

  • 255 + 1 = 0(模 256)

这就是“模运算”思想。

所以说:

在计算机中所有运算都是在 “模 2ⁿ” 的世界中进行的,因为数据位数是固定的。超出后就“回绕”或“溢出”了。

用术语说,这叫“模运算”,也叫“有限域计算”。

 那负数怎么办?

比如在 8 位二进制中,计算是模 256 的运算(也叫 模运算 Modulo Arithmetic):

如果你想表示 -5,你就找一个数,使得:

而 251 的二进制就是: 

-5 的补码表示 = 251 = 11111011(二进制)

这正是 -5 的 补码表示!

所以: 

在 n 位二进制系统中,我们处理的数值其实是模 2^n 意义下的数。

✅ 关键:补码本质上就是用模 2^n 的“逆元”来表示负数

为什么 “取反 + 加1” 等价于模逆?

我们来从数学上拆解它:

1️⃣ 什么是补码?

假设我们有一个 4 位的系统(为了简单,不要一下就上 8 位) 

一共从 0 到 15,这就是“无符号数(Unsigned Number)”的范围。

但我们希望这4位可以同时表示正数和负数,怎么办?

问题来了:负数去哪儿了?

答案是:我们偷偷把后面一半的数字拿来表示负数!

也就是说:

二进制实际代表的数(有符号)
00000
0001+1
0010+2
0011+3
0100+4
0101+5
0110+6
0111+7
1000-8 ⬅️ 从这里开始
1001-7
1010-6
1011-5
1100-4
1101-3
1110-2
1111-1

你看:我们把“后面8个”二进制数,安排给了负数的补码表示。

负数应该对应哪个正数的“谁”?

我们来看看 -1 对应什么:

-1 的补码 = 1111
1111(四位) = 15(无符号),也就是 2⁴ - 1

所以你看出来了吧?

负数 x 的补码,其实就是 2ⁿ - |x|

所以:

  • -1 的补码 = 2⁴ - 1 = 15 = 1111

  • -5 的补码 = 2⁴ - 5 = 11 = 1011

所以补码是:

例如:在 8 位中,-5 的补码是:

2️⃣怎么快速求出 2ⁿ - x 呢?

那我们能不能用一个“简单的方法”算出 251?

当然可以。看这个分步过程:

第一步:对正数 00000101 取反

得到:11111010 👉 相当于 ~x(按位取反)

第二步:加1

11111010 + 1 = 11111011

结果就是 256 - 5 = 251

所以“取反 + 加1”是一种快速求出 2^n - x 的方法!

这个值,正是 -x 在补码中的表示方式。

为啥加这个补码就能完成减法?

因为你做的是:

7 + (2^n - 5)

如果你是在 4 位的机器上,2ⁿ = 16,那:

7 + (16 - 5) = 7 + 11 = 18

但是,4 位机器只能保留最后 4 位(二进制): 

18 = 10010 → 留最后 4 位:0010 = 2 ✅

你看到没有?

在限制位数的计算里(模 2ⁿ),加上负数的补码就等于减法

总结:“取反 + 加1”的设计原因

目的为什么这么做?
✅ 统一加减法为加法减法变成加上“负数补码”
✅ 用硬件实现简单取反+加1可以用电路很快做出来
✅ 本质是模运算2^n - x 就是负数在模系统中的等价表示
✅ 避免复杂进位逻辑比如反码要尾加进位,补码不需要

相关文章:

  • 信息最大化(Information Maximization)
  • 大模型在创伤性脑出血全周期预测与诊疗方案中的应用研究
  • leetcode刷题日记——二叉搜索树中第 K 小的元素
  • 从认识AI开始-----AutoEncoder:生成模型的起点
  • Web前端基础
  • ELK日志管理框架介绍
  • XSS(跨站脚本攻击)详解
  • 对称哈希连接实现
  • ECharts 提示框(tooltip)居中显示位置的设置技巧
  • 学习STC51单片机30(芯片为STC89C52RCRC)
  • Jina AI 开源 node-DeepResearch
  • 网络协议通俗易懂详解指南
  • 应用层协议:HTTPS
  • 物联网技术发展与应用研究分析
  • 【AUTOSAR COM CAN】CanTSyn模块技术解析
  • ubuntu显示器未知
  • MobX与响应式编程实践
  • MySQL:分区的基本使用
  • 外贸网站服务器选择Siteground还是Hostinger,哪个更好?
  • 【C/C++】STL实现版本为什么比手写版本高?
  • 做网站优化公司/体验营销
  • 做医学网站/搜索引擎优化方法与技巧
  • 做企业网站织梦和wordpress哪个好/站长之家怎么用
  • 技术支持 沧州辉煌网络-网站建设/百度网盘下载
  • 163网易免费邮箱登录/长沙网站seo排名
  • 哪个cms做企业网站好/新闻最新消息10条