8位存储-128引发的思考

来源:互联网 发布:不忘初心的理解 知乎 编辑:程序博客网 时间:2024/06/04 17:42

学习中会遇到一些看似简单的问题,但是问题后面会引发多个疑问,一点一滴的积累才是最重要的;
不能够把简单问题彻底弄清楚,也就成不了高手,问大家两个简单问题:
计算机中为什么采用补码才存储数据?为什么8位二进制可以表示-128?
如果你能够在几秒钟内说出原因,那证明你的看书看的很仔细,如果不能够准确答出,那就要跟着我一起来回顾
刚上大学时学过的知识了,温故而知新这个道理其实很深奥。
原因:
1. 原码的不足:0的二异性,+0的原码 = 00000000(8位来算);-0的原码:10000000;
2. 用原码进行四则运算时,符号位需要单独处理,且运算规则复杂;
3. CPU中,一个最小的运算单元(三极管)就是一个与非门,所有的运算加、减、乘除都要转换成与非运算,
每次与非运算都要是耗时间的,采用补码,进行与非运算的次数会最小,提高运算效率;
使用原码会提高使用寄存器的次数,效率差;
4. 负数采用补码之后,可以使加减统一为加法运算;使符号位能与有效值部分一起参加运算,从而简化运算规则;
正是由于上述原码的不足,促使人们去寻找更好的存储方式:补码。

补码思想的一个好例子:
时钟问题:假如准确时间为6点,现在时间是8点,那么顺时针拨10个小时和逆时针拨2个小时的效果是一样的;
即(8 - 2) = (8 + 10) mod 12;在模运算中,一个数减去另一个数,可以转化为一个数加上另一个数的补数。
注:
正数的原码 = 正数的补码 = 正数的反码
负数的反码,除了最高位符号位不变,其他位取反;
负数的补码,除了最高位符号位不变,其他位取反,并在末位加1;
补码转为为原码:
如果补码为正数,则原码为其本身;
如果补码为负数,则除符号位,各位取反,末位加1;
错误例子:
1 + (-1) = 0;
但是从原码角度来计算:
 0000 0001
+1000 0001
----------
 1000 0010
结果为-2,显然不正确,证明用原码来计算是存在错误的。

其实,我们可以得到8位负数的补码,-1的补码为0xff,-2的补码为0xfe, ... ,-127的补码为1000 0001;

我们发现一个规律:补码随着负增值的变大,反而越来越小,到-127时变为1000 0001,

那么我们可以很快得出-128的补码为:1000 0000;即用-0来表示-128;

负数的补码随着负数的增长而变小这个规律是正确的,因为我们把值还原的话,正是在补码的基础上求反再加1;从而可以得到-1的补码0xff还原之后,除去符号位,变成了除了-0之外,最小的数1;而-128的补码0x00还原之后,得到的原码为:1 0000 0000,除去溢出的符号位,正好为0。

 

举例1(8位计算):
-1 + 3 = 2:
-1原码:1000 0001
-1反码:1111 1110
-1补码:1111 1111
即:0xff
3原码:0000 0011
3补码:0000 0011
-1 + 3表示:
 1111 1111
+0000 0011
-----------
10000 0010
高位溢出,最后结果为0000 0010,转化为原码为正数+2,结果正确。

举例2(8位计算)
-2 - 3 = -5:
-2补码:1111 1110
-3补码:1111 1101
 1111 1110
+1111 1101
-----------
11111 1011
高位溢出,得出结果为:1111 1011,再转化为原码为:10000101,结果为-5,正确。

深度挖掘:
char类型的范围为-128~127,占8位;
8位二进制数的原码和反码表示不了-128,只能表示-127~+127之间的数:
-127: 1111 1111
127: 0111 1111
只有补码才能表示-128:
-127 - 1 = -128
-127补码:1000 0001
-1补码:1111 1111
-127 - 1:
 1000 0001
+1111 1111
-----------
11000 0000
高位舍去得:1000 0000,转化为原码为:1111 1111 + 1 = 1 0000 0000;
因为+0和-0都是0,有重复,所以在八位二进制中就把-0当作最小数-128用;
即1000 0000;

记住:在八位二进制中,为了区分+0和-0的区别,就把-0当作最小数-128用,即1000 0000;
那么-129至少需要9位才能存下来,因为没有一个特定的像-0这种特例来表示它,所以-128很幸运
可以用8位来存储。
-128 - 1 = -129:
 1000 0000
+1111 1111
-----------
10111 1111
高位截取后变成了正数,很奇怪吧?结果为0x7f;

那首次溢出结果为0的数是哪一个呢?
答案是-256.
原因:
-255补码为:1 0000 0001
-1补码为:    1111 1111
相加结果为10 0000 0000,溢出后截断低8位得:0000 0000,原码为0.
很有意思吧?

0 0
原创粉丝点击