补码原理的一种理解
鄙人在学习补码的时候遇到一些疑问,在模,取反加一问题上似乎并没有清楚的看见本质。在查阅众多其他作者的理解后,还是点迷迷糊糊,下面我将通过“取反加一”,“模”两个概念来讲讲我对补码的理解。
补码的意义
在计算机中我们都用二进制在存储数据而,为了表示负数我们先提出了“反码”的方法,最后在反码基础上加1提出了“补码”的方法,把数据放入栈中,(这是一种方程的思想来解决负数存放的问题)
补码的形式
8位的位模式下二进制表示
我们的规定是
补码 = { 最高位为 0 表示正数 最高位为 1 表示负数 补码=\begin{cases} 最高位为0 & 表示正数 \\ 最高位为1 & 表示负数 \\\end{cases} 补码={最高位为0最高位为1表示正数表示负数
在此可以列出其表示的所有值(8位)
0000 0000
0000 0001
0000 0010
…
0111 1111
…
1000 0001
1000 0010
…
1111 1111
注意在表示的时候我们有2个特殊的值
== { 00000000 = 0 10000000 = − 128 \begin{cases} 0000 0000 & = 0 \\ 1000 0000 & = -128\\\end{cases} {0000000010000000=0=−128
所以8位表示下我们的范围为【-128,127】
取反加一
反码是在原码的基础上:符号位不变,其他位取反
补码是在反码的基础上:在加一
eg:
十进制 | 二进制 | 二进制补码 |
---|---|---|
34 | 0010 0010 | 0010 0010 |
-34 | 1010 0010 | 1101 1110 |
如34的二进制为 0010 0010 ;-34的二进为1010 0010 在取其补码时
符号位不变 仍为1(为高位)**其它的各位 **取反就是010 0010➡101 1101最后加1➡101 1110
模的方法(本质)
看了很多人的文章,他们都把取反加一视为神来之笔,不可否认,但是补码重点在于“补”
我们用时钟来举例
如果现在是5点,我想把它拨到7点可以怎么做?
- 向前拨2格 5 + 2 =7
- 向后拨10格- 10 =-5 那么-5相当于在12往后又走5格 也是=7
对可以发现 5 + 7 =12
这表明在存在溢出的时候:上溢出(overflow)就会把我们的模向前进一位而这一位是不显示出来的
eg:0111 1111 + 0000 0011 = 0000 0010
127 + 3 = 2 (+ 128 128为第8位而不显示相当于被丢弃了)
而我在理解的时候却出现了一个问题 为什么模是128而不是127(除去最高位表达的最大值为127)
现在我们拿方程的思想来从整体看看问题
可以确定 1 + x = 0 求解 x = -1
那么我们 0000 0001 + x = 0000 0000 这个正确的x值应为-1(1000 0001)
解方程的话x = 0000 0000 - 0000 0001 = 1 0000 0000 - 0000 0001 =1111 1111
所以我们的结论是,一个正数对应的负数(也就是俩相反数),这两个数的二进制编码加起来必须等于0才对,所以我们只要知道其中一个数的编码x,然后用0-x就是他对应的数的编码 观察两个数
-1的二进制值 |
---|
原码 1000 0001 |
补码 1111 1111 |
两者相加刚好等于0 这就恰恰解释了在存储数据时 减去一个数 = 加上|模加上这个减数|
综上的观察 我们模=128的时候刚好时溢出的临界值 只有“和数”向上溢出(overflow)才符合我们的 减去一个数 = 加上|模加上这个减数| ; 在上面我们这使用的是1 0000 0000 - 0000 0001 来完成我们的减法运算
综合解释
我们以自己为主人公来创造补码解法的角度来看看为什么我要这样做
在原码上 取反(上述方程思想)就是为了溢出(进位舍弃) 而要溢出我们的最大值127必须加1(上述减法运算的启示)才能溢出;这也就取反加一 的理解
以上说法均为个人领悟,加之文笔有限,在表述上可能会产生让您有不解的地方,错误难免,望不吝赐教