原码反码和补码的区别及用法笔记
之前学习原码、反码、补码的时候就学的很懵,知道反码和补码怎么算的,但是不知道有什么用。
今天看了几个视频,虽然有举例,但是自己换了个数就算不出来了。后来终于弄明白了。
在这里记录一下。也为其他同学提供一下参考。
二进制简述
我们生活中使用的都是十进制的,但是计算机用的是二进制的。
十进制的意思就是逢十进一,二进制的意思就是逢二进一,当然对应十六进制就是逢十六进一(所以十六进制对应的9后面不进位而是ABCDEF)。
由于二级制的话,每一位刚好又对应了2的n次方,所以在一些教程里,经常看到有人问8 4 2是怎么来的。
下面以二进制的 1111 举例说明(对应十进制的15,十六进制的F)
二级制(无符号) | 第4位 | 第3位 | 第2位 | 第1位 |
---|---|---|---|---|
对应计数(从0开始计数) | 3 | 2 | 1 | 0 |
二进制值 | 1 | 1 | 1 | 1 |
对应2的次方表示 | 2^3 | 2^2 | 2^1 | 2^0 |
对应十进制表示 | 8 | 4 | 2 | 1 |
上面这个例子是原码无符号的情况。日常中我们提到的大多都是原码形式。
有符号和无符号
如果有符号的情况,约定最高位就用来作为正负号,0代表正号,1代表负号。
这个时候 二进制1111在无符号数的时候,转换为十进制是15,作为为有符号数的时候对应十进制是-1
原码、反码、补码的计算方式
当开始讲原码、反码、补码的时候通常会举例。
例如:
对于十进制1对应的四位二进制,原码是 0001
如果是十进制-1,对应原码在最高位加个符号位,即 1001即可
此时对应的反码,符号位不变,其他位取反,1变0,0变1,即1001对应的反码为1110
对应的补码就是反码+1,即 1111。
十进制 -1
原码 | 1 | 0 | 0 | 1 |
---|---|---|---|---|
反码操作(相对原码) | 最高位符号位不变 | 取反 | 取反 | 取反 |
反码 | 1 | 1 | 1 | 0 |
补码操作(相对反码) | 不变 | 不变 | 不变 | 加1 |
补码 | 1 | 1 | 1 | 1 |
有的教程讲到这里,就讲完了。
补充的理解
讲到这里我觉得只说清楚了怎么算出来的补码,但是还没解释怎么用的。
然后我又去查了怎么用的,发现是在计算的时候。
这里说明一下,不能大于实际表示范围的计算,为了解释比较方便,使用4位的2进制数,所以实际对应十进制范围是-8~7。下面举例子的加减前和加减后的值都不能超过这个范围才行。
计算加法的时候是不用补码的,只有计算减法才用到。
由于计算机的逻辑电路的原因,实际上只能进行加法运算。
例如:十进制2-1,不能直接使用2-1,要使用2+(-1)
即:
0010
+1001
这里是原码,如果直接加的话,结果是1011为-3,结果显然是错的。
就需要使用补码。补码就是在原码基础上+1。(有的老师解释为是因为计算过程中有了进位,进到了第五位,但是第五位不存在,所以需要用+1来补足。但是有的老师说是因为我们在处理0000和1000的时候,将0000作为0,导致1000变成了-1产生了1位的偏移量,所以在计算时要补全。)
十进制 | -1 |
---|---|
原码 | 1001 |
反码 | 1110 |
补码 | 1111 |
这时候使用补码进行计算
0010
+1111
=0001
得出的结果是1,这个时候,是没有问题的。
但是在遇到2-3的收
十进制 | -3 |
---|---|
原码 | 1011 |
反码 | 1100 |
补码 | 1101 |
十进制 2-3
0010
+1101
=1111
刚刚 2-1 = 0001 = 1 但是2-3 = 1111 = -7 和结果显然不符。
这个时候可能会产生疑惑。
要注意,在计算的过程中,符号位是参与计算的。但是在计算完成后。
计算结果是补码。需要转换回原码,才能得到正确的数值。
由于整数的补码还是自己,所以2-1的结果,不需要还原,就是正确的值。
但是2-3的结果是负数,就需要还原成原码。
补码 1111 还原反码需要 -1 为 1110, 还原为原码需要保留符号位,反转其他位,变成 1001 即-1
我当时上学的时候这里就是没有搞明白,最近重拾C,又遇到这里,看了好多个教程,终于搞明白了,这里原来要还原回去。
但是
实际上计算机存 -1 如果使用四个bit,存的就是 1111 我们对于负数,还原成原码只是为了读取方便。
前面提到,我们用四位表示有符号数的时候,只能表示 -8到7之间的数值。
这个时候按照下面的表格来理解,就更容易理解了。
二进制 | 十进制 | 二进制计算 |
---|---|---|
0111 | 7 | 减1 |
0110 | 6 | 减1 |
0101 | 5 | 减1 |
0100 | 4 | 减1 |
0011 | 3 | 减1 |
0010 | 2 | 减1 |
0001 | 1 | 减1 |
0000 | 0 | 减1 |
1111 | -1 | 减1 |
1110 | -2 | 减1 |
1101 | -3 | 减1 |
1100 | -4 | 减1 |
1011 | -5 | 减1 |
1010 | -6 | 减1 |
1001 | -7 | 减1 |
1000 | -8 | 减1 |
0111 | 7 | 减1 |
特别注意最后一行,和0到-1的时候,这里在二进制4bit计算上是连续的(类比十进制,200-1为199,如果只十位数和个位数,就变成了,00减一之后的数是99)
我们可以看到,计算机存储时在按位加减法上,数值是连续的,计算上也不会存在问题。也不需要进行原码补码反码的转换。
这里我认为可能导致学习困难的原因是因为,我们但凡学过数学的同学,都会认为整数应该是连续的。
由于教学的都是从原码开始教,而没有讲到实际的存储情况,导致学习的人产生了数域不连续的印象,而导致了学习上的困难。
实际的在加减法中,使用不到原码和反码,直接按照实际的进行加减运算,这才是符合算术逻辑辑的,更容易理解。
要注意,我们常用的十进制和二进制,抛开计算机限制,在数学运算上,没有本质区别。但是在计算机上,由于硬件的限制,不能使用无限位数,所以在有符号时使用了最高位作为符号位。并且存在溢出到下一位的问题。这样,这部分内容应该就很好理解了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)