首页 > 为什么二进制取反加一的操作是可逆的?

为什么二进制取反加一的操作是可逆的?

补码取反加一是原码
原码取反加一是补码
求大神解释一下


这其实只是原码和补码表示的意义所使然的。简单的说,可以想想在二进制表示中,即存在一个 +0 还存在一个 -0,那在直接取反的过程中,其实就自动少了 1,这时候要加 1 才能保证再次取反能回归原数(再次取反时又会少一,还得加)。


以8位二进制为例。

根据定义,正数a的反码就是原码,-a的反码是a的原码高位取1,其他位求反(就是a的反码所有位求反)。所以a和—a的反码所有位都不同。如果把他们都当做无符号二进制数,则他们的和等于(11111111)b,也就是255。因此 a反+1=256-a。做两次这样的操作就是256-(256-a)=a,也就是你说的可逆的:这仅仅是是一个逆函数是自身的普通函数而已。

至于为什么使用补码来表示数字? 8bit二进制数,一共有256种情况,我们使用 0...255表示,所以只能表示 256个整数,当我们需要有符号数的时候,就只能表示 -128~127。其实,用0表示-128,1表示-127,....,255表示127,就挺好的了(满足所有合理的数学运算)。可是这种方式总是不符合人类的习惯,人们还是习惯0表示0....。

所以,我们要求可以满足四条:1、线性映射(规则简单);2、合理的处理计算溢出的情况;3、计算机处理起来方便;4、符合人类的习惯;

所以最终方案是:0~127 用 0~127 表示, -128~-1 用 -128~-1 + 256 = 128~255来表示。原码,反码,补码的概念就是人们在设计数字电路的时候,优化这个+256的时候出现的概念。总结一下就是 正数的补码是原码,负数的补码就是 负数+256 的原码。

这仅仅是模256的加法群的一个同构群。加运算就是(补码对应的二进制正整数)结果的补码=(补码1+补码2)MOD 256。因此即使溢出了也仅仅是与正确的结果相差256的整数倍。


取反加1更多的是根据转换规则总结出来的“口诀”,所以要理解为什么,还是要搞清楚补码和原码之间是如何转换的。

补码的定义是:模-原码,模是2^(n-1),这里n为数的位长。例如对于8位的单字节有符号整数来说,补码=2^7-原码。(因为8位有符号数的最高位为符号位,所以实际上用来表示数的绝对值大小的只有7位)

为了便于理解,下面的计算都以8位数来做例子,就不用别扭的n来表示了。

模 = 2^7 = 10000000 (1后面7个0)

而:原码+反码 = 1111111 (7个1) = 2^7 - 1

移项:2^7 - 原码 = 反码 + 1

等式左边正好是补码的定义,所以补码自然就是反码+1了

这就是补码=原码取反+1的来历。再来看看怎么用补码求原码。

因为:补码 = 反码 + 1
所以:反码 = 补码 - 1

两边同乘以-1,并且同时加上1111111(7个1):

1111111 - 反码 = 1111111 - 补码 + 1

等号左边正好是原码,等号右边的“1111111 - 补码”部分正好是“补码的反码”,所以:

原码 = 补码的反码 + 1

因此原码=补码取反+1


题主的说法是有问题的
取法加一其实就是对任意数A, 取-A的补码形式
先假定任意数A为八位.
取反加一实际上11111111 - A(补) + 1 = 100000000 - 1 - A(补) + 1 = 100000000 - A(补) = 0 - A(补) = (-A)(补)

一定要认清数和编码之间的区别,不然很容易混淆


只是进位之后会消除。


设原码为A,用N位二进制数字表示。则:

  1. 取反后得:2^N-1-A;(这一步是因为反码和原码的和是2^N-1得到的)

  2. 加一后得:2^N-A,即补码,记为B

  3. 再取反后得:2^N-1-B,即2^N-1-(2^N-A)A-1

  4. 再加一后得:A

完毕。

以上证明了:~(~A+1)+1=A

其实可以这样理解:

  1. 首先~(~A)=A很好理解吧,因为一个数取反两次肯定等于原数嘛。

  2. 然后两次加1,分别是在取反一次后和取反两次后进行的。所以两次性质相反,相当于一次是+1一次是-1,抵消了。

  3. 推广一下就是:~(~A+M)+M=A

【热门文章】
【热门文章】