二进制数的有效讨论

为什么-128的二进制表示是10000000?

这里面就要讨论到有关于真数在计算机中表示了。

在计算机内部,所有的信息都是由二进制数串表示的,这其中就分为了无符号有符号。无符号的整数用来表示正数和0,有符号的整数则可以用来表示全体整数。

由于计算机中的整数全部由二进制表示,所以正负号也全部由0(正)和1(负)表示。一般来讲,将进制中的最高有效位设置为符号位。将一个真值表示成二进制数串的机器数的过程被称为编码。

而其中,规定真值在计算机中的二进制表示通通由它们的补码表示。为什么要用补码?

  • 因为补码可以将符号位与其他位统一处理,同时减法也可以按加法来运算,即如果是补码表示的数,不管是加减法都直接用加法运算即可实现;
  • 两个用补码表示的数相加时,若果最高位有进位则舍弃进位。

这样做的好处是:

  1. 是符号位能够与有效值部分一同参加运算,简化运算规律。从而可以简化运算器的结构,提高运算速度;
  2. 加法运算比减法运算更易于实现。进一步简化运算器线路设计

下面深入分析采用补码的原因:

用带符号位的原码进行乘除运算时结果正确,而在加减运算的时候就出现了问题 ,如下:

1D-1D = 1D + (-1D) = 0D
(00000001)原 + (10000001)原 = (10000010)原 = -2

这显然是错误的。因为在两个整数的加法运算中是没有问题的,于是就发现问题出在带符号的负数上。

用带符号的反码进行运算,如下:

1D- 1D = 1D + (-1D) = 0D
(00000001) 反+ (11111110)反 = (11111111)反 = ( -0 ) 有问题。

1D - 2D= 1D+ -2D = (-1)D
(00000001) 反+ (11111101)反 = (11111110)反 = ( -1 ) 正确

问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的。

现在再来看下有符号的补码运算,如下:

1D- 1D = 1D + (-1D) = 0D
(00000001)补 + (11111111)补 = (00000000)补 = 0D

1D + 1D = 2D
(00000001)补 + (00000001)补 = (00000010)补 = 2D

由此可以证明计算机中的带符号运算都是基于补码实现的。

二进制中的特殊值

反码表示法规定:正数的反码就是其本身。负数的反码保持符号位不变其他按位取反。
而8位二进制能表示的反码范围为:-127~127.
此时-128没有原码和反码。这是因为-0与-128的反码一致,且看:

-0 = (10000000)原 = (11111111)反
-128 = (10000000)原 = (11111111)反  [**<span style='color:red'>假设</span>**]

此时,-1与-128的反码冲突,所以当有了-0的原码反码时就不该有-128的原码反码。

我们再来看一下八位二进制中的原码、反码、补码的范围:

原码:-127~127
反码:-127~127
补码:-128~127

此时会发现补码比反码多了一个,这是因为0这个因素。

+0: (00000000)原 (00000000)反 (00000000)补
-0:  (10000000)原 (11111111)反 (00000000)补 

**需要说明为什么-0的补码还是00000000**

补码本质是用来构成一个环,以实现一个同余运算。以8位整数为例,取得的结果永远是2^8次方的余数,这与有无符号无关。

用计算器做加法运算时,实际上做的是同余加法,即:
1+2 ≡ 1(mod 256)+ 2(mod 256) ≡ 3(mod 256)
这样做的好处是无论所运算的是否为有符号,都可以使用同样的运算规则。

256的余数总共就256种,分别是0~255。但是我们希望表示一个负数,那怎么做呢?
255 ≡ -1(mod 256) ≡ 255(mod 256)
于是乎就用255来表示了。考虑到取值范围,以及为了方便区分,我们定义有一半的数是正数、一半的数是负数,恰恰就是二进制最高位为1则是负数,最高位为0则表示正数范围,这个就是补码的本质。

至于补码的计算方法,也就是取反加1,完全是因为:
x+~x ≡ 255(mod 256)
这与『符号位』无关,它的逆运算,其实求解的是:
x+~x+1 ≡ 0(mod 256)
可以得出:-x ≡ ~x+1(mod 256)

此时把0代入可得:-0 ≡ ~0+1(mod 256) ≡ 255+1(mod 256) ≡ 0;

所以,补码能表示的数的个数中,比原码反码少了一个,所以补码可以多表示一个真值为-128的数。
但是,多表示的这个数-128比较特殊,只有原码和补码,没有反码。
-128的补码是1000 0000。

为什么-128的补码是10000000呢?
可根据上文进行推导:
-128 ≡ ~128+1(mod 256) ≡ 127+1(mod 256) ≡ 128;
所以-128的补码与128一致即为10000000。

本文内容借鉴了一些前辈的观点:

作者:今天还是要喝水 链接:https://www.cnblogs.com/flowerslip/p/5933833.html

作者:Coldwings 链接:https://www.zhihu.com/question/21511392/answer/82989720

原文地址:https://www.cnblogs.com/njuptzheng/p/14471357.html