15.04.10-有意思的补码

最近在看《深入理解计算机系统》,学习编程的一些基本的东西,还是觉得很有意思的。

今天看到了补码编码这一节。

最常见的有符号数的计算机表示方式就是补码(two's-complement)形式。在这个定义中,将字的最高有效为解释为负权(negative weight).我们用函数B2Tw(Binary to Two's-complement的缩写,长度为w)来表示。

最高有效位xw-1也称为符号位,它的"权重"为-2w-1,是无符号表示中权重的负数。符号位被设置为1时,表示值为负,而当设置为0是,值为非负。

仔细看前面那个公式,尤其是前面的-xw-12w-1

那常见的32位整数来看,如果数值为

11111111 11111111 11111111 11111111

= -1*231 + 1*230 + 1*229 + 1*228 +...+ 1*21 + 1*20

=-231 + (231 - 1)//不要问这个结果怎么来的,XXX-_-||求和公式....

=-1

那好,其他的呢?

11111111 11100011 11011101 11110011

= -1*231 + 1*230 +...+ 1*221 + 1*217 +...+ 1*214 + 1*212  + 1*211 + 1*210 + 1*28+...+ 1*24+ 1*21+  1*20//少了2/3/9/13/18/19/20

= -1*231 + (1*230 + 1*229 + 1*228 +...+ 1*21 + 1*20) - 22 - 23  - 29 - 213 - 218 - 219 - 220 

=-231 + (231 - 1) - 22 - 23  - 29 - 213 - 218 - 219 - 220 

=- 1 - 22 - 23  - 29 - 213 - 218 - 219 - 220 

看到这里是不是想起了什么了?

对了,就是常用的负数的二进制表达式的写法。

37(int32)的二进制表达式为 00000000 00000000 00000000 00100101

-37的写法呢:

首先反码:11111111 11111111 11111111 11011010,值是多少?

11111111 11111111 11111111 11011010 = -1 - 20 - 22  - 25 = -37-1

所以在反码的基础上,我们还要+1,才能得到-37的二进制码:

11111111 11111111 11111111 11011011 = -1 - 22  - 2= -37

关于负数的二进制表达式,刚看到补码非运算时看到另一个方法。

先说补码非

上面的非可以理解成我们常说的负值。最后的公式可以看出,如果值为w位的最小值-2w-1那么他的负数(求非)值为本身,其它的情况则为*-1的结果。

计算一个位级表示的值的补码非有几种聪明的方法。

1.对每一位求补,再对结果加1.(也就是我们常见的写负数的二进制表达式的方法。)

2.第二种方法是建立在将位向量分为两部分的基础之上。假设k是最右边的1的位置,从左至右,将位级表达式分为两部分,[xw-1,xw-2,...,xk+1]和[1,0,...,0]。值的非写成二进制格式就是前半部分[~xw-1,~xw-2,...,~xk+1]和[1,0,...,0],合起来就是[~xw-1,~xw-2,...,~xk+1,1,0,...,0]。也就是说从最右边的1往左(不包含这个1)所有位取反。

验证:

1100(-4) ---> 0100(4)

1000(-8) ---> 1000(-8)

0101(5)  ---> 1011(-5)

0111(7)  ---> 1001(-7)

32位:00000000 00000000 00110100 11101011(26859)

求非: 11111111 11111111 11001011 00010101(-26859)

原文地址:https://www.cnblogs.com/icyJ/p/B2T.html