透彻理解原码、反码、补码

本文解释了计算机中补码的概念,指出原码并非实际存储形式,而是为了教学便利。通过实例说明如何计算正数和负数的补码,以及在二进制加法中补码的应用规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通常的定义为:
原码为正时,其补码就是原码本身
例如: 47原码为 00101111 补码为 00101111
当原码为负时,其补码为原码除符号位其它取反再加1
例如: -30原码为 10011110 补码为 11100010

如果不想硬背原码补码中那些取反+1的东西,可以接着看下去

But!!!!
很多人不能理解其原理
但其实在计算机中,本就没有原码的概念,所有数字都是按照补码存储的!

补码定义:
设A,B两个数字,若A+B恒等于一个规定的数,则称这两个数互为补码。

注意!这里的数字不是我们规定的原码。
所以你会发现正数的原码+补码不是一个固定的数字
但是负数的原码+补码恒等于100000000

那现在来抛开规定的原码转补码的理论!
数字5的二进制是 00000101
那么其补码是 100000000 - 00000101 = 11111011

11111011?
觉不觉得很熟悉?
这就是 -5 的补码

现在可以理解为在补码中 100000000 - A = -A
所以如果要求一个原码为负数的补码,直接求它绝对值的补码就行。

举个例子,-120的补码,就等于100000000 - 01111000(120的2进制) = 10001000

现在利用这种理论来看看二进制数的加法
例如 A + B(其中 A > 0,B < 0)

如果 A + B > 0
则这两个数字的补码之和肯定是大于100000000的
原因是将 A 拆分成(-B)加上另外一个值,带入到原式子中 其中B-B就等于100000000,再加上A拆分出的另外一个正值就肯定大于100000000,而我们认为B-B同时也等于0,所以相加结果多出来的那100000000我们便舍去了,只考虑后8位

如果 A + B < 0
则这两个数字的补码之和肯定是小于100000000的

综上所述,原码只是教程中用来方便我们理解补码的中间量,如果不想硬背那些取反+1的东西可以参考我上面的说明。
该文章为个人理解,若有错误欢迎讨论。

### 原码反码补码的定义 #### 原码 原码是一种简单的二进制表示方法,在数值前增加一位符号位来区分正负数。对于一个 n 位二进制数,最高位作为符号位:0 表示正数,1 表示负数[^3]。 例如,8 位二进制下,`+5` 的原码为 `00000101`,而 `-5` 的原码为 `10000101`。 缺点在于,原码无法直接用于加减运算,尤其是涉及负数时会出错。例如,`1 + (-1)` 应该等于 `0`,但在原码中计算结果却是错误的[^3]。 --- #### 反码 反码是对原码的一种改进形式。其定义如下: - **正数**的反码与其原码相同。 - **负数**的反码是将其原码除符号位外的所有位按位取反。 例如,8 位二进制下,`+5` 的反码仍为 `00000101`,而 `-5` 的反码为 `11111010`(将 `10000101` 中的低 7 位取反得到)。 虽然反码解决了部分问题(如互为相反数相加得零),但它仍然存在问题,特别是在处理两个负数相加时容易出错[^3]。 --- #### 补码 补码进一步优化了反码的设计,广泛应用于现代计算机系统中的数值表示和运算。具体定义如下: - **正数和零**的补码与它们的原码一致。 - **负数**的补码通过以下方式获得:先求其反码,再对反码加 1[^3]。 例如,8 位二进制下,`+5` 的补码仍是 `00000101`,而 `-5` 的补码为 `11111011`(由 `-5` 的反码 `11111010` 加 1 得到)。 补码的优点在于它能有效解决加减法运算中的溢出问题,并支持统一使用加法器完成各种运算操作[^2]。 --- ### 原码反码补码的应用场景 #### CPU 和硬件层面 在计算机内部,所有的整数运算几乎都基于补码实现。这是因为补码可以简化硬件设计,使得加法器既能执行加法也能间接完成减法操作[^1]。例如,当需要计算 `A - B` 时,实际的操作被转化为 `A + (-B)`,其中 `-B` 是以补码形式存储的值。 #### 数据类型范围扩展 采用补码还可以扩大有符号整型的数据表示范围。例如,8 位二进制数用原码反码表示时,可覆盖区间为 `[-127, +127]`;但如果改用补码,则能够表示更广的范围 `[−128, +127]`。 #### 高级编程语言 尽管程序员通常接触的是原码形式的输入输出(如 C/C++ 或 Python 中显示的结果),但实际上这些数值会被自动转换成补码供处理器处理[^1]。因此,了解三者之间的关系有助于深入理解程序运行机制及其潜在性能瓶颈。 ```c #include <stdio.h> int main() { signed char a = -5; printf("Complement of %d is represented as: %hhu\n", a, *(unsigned char*)&a); return 0; } ``` 上述代码展示了如何查看变量 `-5` 在内存中的补码表现形式。 --- ### 总结 综上所述,原码主要用于直观表达数值,便于人类阅读;反码则试图修正某些特定情况下的计算误差;唯有补码因其高效性和兼容性成为主流标准,适用于绝大多数现代电子设备的核心算法逻辑之中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值