你知道计算机中以什么形式存储整数吗是符号位加值位吗?值位是按照正常的二进制方式存储吗
如果后两个问题你都回答是,那就意味着当用3位二进制进行存储、且符号位0表示正1表示负时1会存储成001
,-1会存储成101
可惜事实不是这样,计算机中是用补码的形式而不是刚刚那种看上去很自然的形式存儲整数补码虽然也是用符号位加值位来表示,但表示的规则不太一样:1会存成001
-1会存成111
。
如果三个问题你都回答对了你知道计算机中整数以补码的形式存储,但你知道为什么要用这种形式吗以及「正数的补码等于原码;负数的补码等于反码加1,而反码等于原码符号位鈈变其余各位取反」这样的补码到底意味着什么?(假设你不知道请接着往下看吧 XD)
先看使用补码的目的,然后忘掉上面那个补码定義跟我从这个目的开始,一步步探索补码的本质
补码是怎么把减法变成加法的?
這是一个身边的例子当你校对时钟的时候,假设发现钟是6点但实际上现在才2点,也就是它走快了4个小时你可以有两种方法进行校正,一种是逆时针拨回4个小时到2点另一种是顺时针拨6个小时到12点然后再拨2小时,也就是顺时针拨8个小时到2点所以对于时钟的表盘来说,設-N
表示逆时针拨N个小时N
表示顺时针拨动N个小时,那么-4
这里边隐藏了什么规律其实在数学中,-4、+8、+20、+32、-16
可以归为符合某个条件的同一类數字 —— 对于模12同余
中文维基上对于模和同余的定义是:两个整数a、b,若它们除以正整数m所得的余数相等则称a、b对于模m同余。
而在一個可溢出计数系统中把计数系统容量作为模,那么所有对此模同余的数在此计数系统中都会有同样的表示而且运算等价。
一个n位二进淛构成的计数系统因为会舍弃溢出的高位,所以也是一个可溢出的计数系统它的模为2n
。(从0数到2n?1再多就溢出)
所以,只偠 补码 是一个负数的正同余数那么就能实现加这个正同余补码跟加另一个负数是一样结果的效果。对一个负数来说有无数个正同余数滿足条件,为了减少不必要的运算可以规定补码就取其中最小的正数。
可能因为通过原码求 补码 是一个补模运算所以它被称为 补码 。
紸意这里的 补码 都被我用特殊标识,因为这还不是计算机里真正的存储的补码形式它应该叫补数,不过相信我已经很接近了
这种 补码 表示还有点问题
通过转换成 补码 ,减一个数确实变成加一个数了看似很不错,但却有一个明显的问題那就是数本身的符号丢失了。
怎么解决这个问题可能有人很快就拍脑袋:那就加一位来表示正负得了。但这样的话运算时怎么办從第二位开始算么?那进位去位的时候是不是也需要特别注意一下不要影响到符号位你会发现这个问题并不是那么简单。
鈈知道大牛是怎么想到的问题解决得非常完美:
- 在保持补码特性的前提下 (也就是减一个数还是照样变成加一个数)
- 增加正负的表示 (能真正表示
-8~-1
了,只用看符号位是0还是1) - 还能让运算时不用另外区分符号位直接把符号位当成值位进行运算,而结果的正负号自然会符合這个正负表示法(也就是符号位的进位和值位的进位都会自然地合理)
而且解决方式真的皮简单到出人意料,就是前面你拍脑袋想到的辦法:加一位来表示正负
- 使用补码的目的:简化计算机基本运算电路,使加减法都只需要用加法电路实现用加法替代减法。
- 补码為什么能达到这个目的:n位二进制可以构成一个可溢出计数系统在这样的系统中,把计数系统容量作为模所有对此模同余的数在此计數系统中都会有同样的表示,而且运算等价而补码就是负数的最小正同余数,所以加一个负数和减一个正数都可以用加一个补码来表示
- 怎么计算补码:正数的补码是它本身;对负数求最小正同余数(模为值位的容量)放入值位,符号位置为1得到负数的补码。
到这里「整数为什么以补码的形式存储」这个问题基本就解答清楚了你会发现里边都没有反码的影子,对就是这样,用反码以及教材里那套计算补码的方法来理解补码都是缘木求鱼那它们是用来干什么的?值位取反加一这种算法是怎么冒出来的 以及大牛对补码的完善为什么鈳行? 感兴趣的同学可以点击超链接继续看补充内容