目录
知识梳理:原码、反码、补码的基础概念
问题一:.为什么有补码?
问题二:.补码中将减法转化为加法后面的数学原理。
问题三: 为什么补码的表示范围比原码的表示范围大一位?
问题四:为什么1000 0000表示 -128?
问题五:为什么在计算补码的时候要取反?还要加一?
原码、反码、补码的基础概念
原码:
定义:就是一种计算机中对数字的二进制定点表示方法。它的表示方法就是最高位表示符号位,1代表负,0代表正。
比如:1(原码)= 0000 0001
-1(原码)= 1000 0001
反码:
定义:正数的反码等于它本身;
负数的反码就是负数的原码在符号位不变的基础上,其余各个位取反;
+1 = 0000 0001(原)= 0000 0001(反)
-1 = 1000 0001(原)= 1111 1110 (反)
补码:
定义:正数的补码是它本身;
负数的补码是它的反码再+1;
+1 = 0000 0001(原)= 0000 0001(反)= 0000 0001(补)
-1 = 1000 0001(原)= 1111 1110 (反)= 1111 1111(补)
负数在计算机里面的储存方式一般都是以补码的形式存在的。
问题与思考
问题一:.为什么有补码?
其实就像数学中的四则运算一样,你可以把补码看成是用加法代替减法,比如你现在减去一个数,其实你就是加上这个数字的相反数,也就是说+(-数字),这样的话,在计算机中,就可以用加法表示减法了,一个数字和他的相反数相加的话,那么就是等于零。这就好比如,一个时钟,现在是6点钟整,你要让它去到8点钟整,你的做法就有顺时针拨 2 小时,或者逆时针拨 10 个小时,所以说使用补码可以将减法简化为加法,但是具体是怎么简化的呢?
问题二:.补码中将减法转化为加法后面的数学原理。
首先,我们来了解一下模的概念,“模”是指一个计量系统的计数范围,比如时钟的模就是12,如果超过12,那么就会溢出,导致进位,这里我们不先不讨论进位,13在12进制里面溢出了1个12单位,也就是从0时拨13个小时,时针会回到1时。为此我们记作 13 mod 12 = 1,
mod是指取模操作, 13 mod 12 = 1 即用13除以12后的余数是1.
所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!
现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.
首先介绍一个数学中相关的概念: 同余
取两个整数,a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余。
记作 a ≡ b (mod m)
读作 a 与 b 关于模m同余。
例子:
1.正数:
5 mod 12 = 5
17 mod 12 = 5
29 mod 12 = 5
2.负数:
这里介绍 m = k * n + r (0<r < n) , m是被除数,n是除数,r是余数。
比如:-3 / 2 余数为多少?
-3 = 2 x -2 +1 可得,余数为 1 。
介绍完如何同余定理后,我们回到用加法代替减法的原理上面。
前拨两个小时 = 回拨 10 小时
前拨三个小时 = 回拨 9 小时
前拨四个小时 = 回拨 8 小时
同样的在数学上面
2 mod 12 = 2
10 mod 12 = 2
2和10是同余的,下面引用同余定理的线性运算定理,
如果:
a = b (mod m ) , c = d (mod m)
(1) a ± c = (b ± d ) (mod 12)
(2 ) a x c = (b x d ) (mod 12)
定理证明过程:https://baike.baidu.com/item/%E5%90%8C%E4%BD%99%E5%AE%9A%E7%90%86/1212360?fr=aladdin
现在有:
-2 ≡ 10 (mod 12 ) = 10
7 ≡ 7 (mod 12)
运用线性运算定理:
7-2 ≡ 7 + 10 (mod) = 5,这里我们就将减法转化为加法了。
问题三: 为什么补码的表示范围比原码的表示范围大一位?
从百度上搜索到的这张图,可以明显的看到,补码的表示范围比原码多了一位,而且是为负数(就是-2^n)。
从图中可以看到,原码之中有两个0的表示方法,一个是+0,另一个是-0,但是到了补码里面,0的表示方法只有一个,也就是说补码取消掉了一个零的表示方式,零的表示方式(1000 0000)也就交给了负数。
问题四:为什么1000 0000表示 -128?
根据问题二还有问题三,我们可以了解到,同余定理还有补码的表示范围比原码还要多出一位,多出来的一位给我了负数,由于原码1000 0000表示128,128和-128 关于模256同余,所以-128和128没有区别,但是在补码里面,符号位1表示负数,所以这里1000 0000表示-128.
问题五:为什么在计算补码的时候要取反?还要加一?
让我们来想想前面说的补码的作用,就是将减法转化为加法,在数学上面就是转化为他的相反数?一个数本身加上相反数会等于多少呢?没错就是0,那么同样的,原码加上他的补码还是会等于0的,比如 0000 0001(1) + 1111 1111(-1) = 0000 0000(0),那么我们就有这一道等式,
对于一个数,补码 + 原码 = 0,补码 = 0 - 原码。
对于0 = 我们上面几行文字说, 0000 0001(1) + 1111 1111(-1) = 0,那么就可以将这一道式子进行等价代换:
对于一个数:补码 = 1111 1111 + 0000 0001 - 原码。
移项后有: 补码 = 1111 1111 - 原码 +0000 0001
对于 1111 1111 - 原码 = ?大家可以自己算算,结果其实是这个数的反码,(反码就是全部取反)
例如:
对于1: 1111 1111 - 0000 0001 = 1111 1110
对于2: 1111 1111 - 0000 0010 = 1111 1101
…
大家可以自行运算,这就是反码的由来,
补码 = 1111 1111 - 原码 +0000 0001
根据公式,可以写成:
补码 = 反码 (1111 1111 - 原码 )+0000 0001
这就是表示补码的时候,反码还要 + 1 .
参考资料:
1.《为什么1000 0000表示-128》https://www.zhihu.com/question/28685048
2.《补码、原码、反码的关系》https://www.cnblogs.com/goahead–linux/p/10904701.html
3. 《补码(为什么按位取反再加一):告诉你一个其实很简单的问题》(https://blog.csdn.net/wenxinwukui234/article/details/42119265