Blablabla~
今天重温了《深入了解计算机系统》关于符号数的bianary表示,弄懂了补码的原理。并写了python脚本验证。当初对这块有疑惑是一上来就告诉你,xxx取反加1就是补码,完全不知道为什么这么做,今天抛开这个说法,从我们想要解决问题入手去思考。
目标
我们想要解的问题是:我们知道计算机都是binary的存储,那么这些binary怎么解释或者对应到 带符号的整数呢?
这是我们想要的解决的问题
解决方案(general)
提供了一种翻译机制,就是一个函数,输入是binary,输出是 符号数
def B2S(binary):
reutrn sign_integer
具体方案(detail)
书里的2.2.3章节的这个图比较形象地画出方案细节,具体可以看下1011的例子。-8在左边是灰色的,蓝色的是正的,累加起来。

- def B2U(b):
- #binary to unsigned
- x=0
- b_str = b[::-1]
- for i,v in enumerate(b_str):
- if int(v)!=0:
- x+= np.power(2,i)
- return x
- def test_B2U():
- assert B2U('0001') == 1
- assert B2U('0101') == 5
- assert B2U('1011') == 11
- assert B2U('1111') == 15
-
- def B2T(b):
- #bianry to two's component
- x = 0
- b_str = b[::-1]
- idx = len(b_str)-1
- for i,v in enumerate(b_str):
- if i
- if int(v)!=0:
- x+= np.power(2,i)
- else:
- x += -int(v)*np.power(2, i)
- return x
- def test_B2U():
- assert B2U('0001') == 1
- assert B2U('0101') == 5
- assert B2U('1011') == -5 # -8+2+1
- assert B2U('1111') == -1 # -8+4+2+1
本质上,我们知道符号数的第一位来表示符号,0表示正,1表示负,那么实际的数值就是:
- 最大的值: 0111, 2^n-1
- 最小的值: 1000, - 2^n
- 一般的值:(-v)*2^n+ 其他项
明白了最小的值是1000,结合上面的图,那么任意bit的整数,-1的表示都是0xfffff。。。
补码:对于任意x, 我们用
来表示 -x的w位表示
另一个思路是,x+(-x)=0 那么,-x = 0-x = 2^w - x = 10000 -(x) 这个思路很好(但是我们不应该记住结论/公式:负数的binary就是其整数取反再加1,记住过程,我们希望x+(-x)=0,所以-x = 0000- x
总结
这套方案(函数),在计算机里叫做 "补码编码". 一般都使用补码的形式来表示有符号整数。弄明白了计算机使用补码(two's component)的编码方式来表示负数(即符号数)。本质就是制定一个规则,一个bianry怎么serialze 到有符号数,这个规则就是一个函数,就是我上面写的B2T,这个函数叫做补码编码。
unsigned char x=0;
printf("%u", x-1); #255