32位intel的CPU中,int类型为什么最小值为-(2^31) ?

以 4 位为例,我的理解是:
有符号数原码:
0 000 ~ 0 111   +0 ~ +7       前面的 0 表示是正数。
1 000 ~ 1 111   -0  ~ -7        前面的 1 表示是负数。
因为 +0 和 -0 实际上是相等的,也就是说,0 用原码表示的话有两种方式,这样的编码虽然人看起来要好懂一些,但是对于计算机来讲,有三个坏处:
1,违反了唯一性
2,浪费了一个位模式(排列方式)。因为理论上来讲 4 位二进制能表示 2^4 = 16 个不同的数,但是这里只表示了 -7 ~ +7 15 个数。
3,-7 明明是小于 -0 的,但是如果不把最高位当作符号位来看的话,1000 要比 1111 小。
我着重讲一下第三点。因为我们最终的目标是让符号也能够参与运算,也就是说,任何两个有符号数比较大小的时候,我们希望只需要减一下就可以了,因此原码的 1000 和 1111 它的顺序是反的,很不利于运算。
-128 在原码里是无法表示的。

基于以上三个原因,就引进了补码,在介绍补码之前,我先介绍一下反码:
正数的反码就是原码:
0 000 ~ 0 111   +0 ~ +7     反码
负数的反码就是对原码除符号位以外的其余各位进行取反:
1 111 ~ 1 000   -0  ~ -7      反码
这么做的好处是什么呢?好处是,解决了上面三个问题中的第三个问题。
但是另外两个问题还是没有解决。

下面引入的补码,就是为了解决另外两个问题。
补码:
补码的规则是:正数的补码和原码、反码形式相同。
负数的补码,等于反码 + 1,加 1 的时候,符号位也参与运算,溢出位被丢弃,不影响结果。
也就是说:
0 000 ~ 0 111     +0 ~ +7    补码
(1)0 000 ~ 1 001     -0  ~ -7     补码。
注意反码的 -0 也就是 1111 加了 1 之后,符号位产生了进位,溢出了,溢出之后,剩下的部分正好和 +0 一样了。
也就是说,第一个问题也解决了。

第一个问题解决了,那么就剩下第二个问题了,
因为从 -0 到 -7 依次是:
-7:  1 001
-6:  1 010
-5:  1 011
-4:  1 100
-3:  1 101
-2:  1 110
-1:  1 111
-0:  0 000
+1: 0 001
+2: 0 010
...
...
...
也就是说,还剩下 1 000 这个位模式是没用的,
因此就可以用它来表示其它的数。但是到底应该用它来表示 +128 好呢?还是 -128 好呢?
观察上面的序列,你会发现,如果溢出是正常的话,
上面的数列正好是连续的,
而 1 000 比 1 001 还要小 1,因此用来表示 -128 是合理的。加 1 之后正好等于 -127。
因此就用 1 000 来表示 -128 了。

猜你喜欢

转载自talentluke.iteye.com/blog/789711