今天图灵完备玩到8位有符号和无符号比较大小,有符号参考攻略理解后通过,无符号确怎么也理解不了,直到下午突然开窍,在此记录。
假设存在两个unsigned char a, b
确定a是否严格小于b
那么肯定是作差 b - a, 观察b - a <= 0 或 b - a > 0
接下来进入推理
我们知道可以将a取反与b相加判断溢出位,溢出为1则b>a,否则b<a,为什么????
现在让我们将a,b扩充一位符号位,做差
式1:b-a = b + (-a) = b + (-256 + (255 - a)) (这里没有考虑补码的加一)
要理解这个十字,首先理解负数,8位有符号的负数是什么?
很简单,补码,各位取反加1,为什么?让我们举个例子
76(0100 1100)的负数,怎么办?
按照图灵完备负数一关教会我的思想,将最高位(符号位)为1即为-128
那么-76 其实为-128 + 52,按照各位取反末尾加一我们看看
二进制: 1 0 1 1 0 1 0 0
十进制:-128 +0+32+16+0+4+0+0 = -128 + 52 = 76
这就是补码的本质:将最高位符号位为一时视为-128,后面为加上正数!
那么问题来了,怎么取出这个52?就是说我将最高位视为-128后正数位怎么确定?
很简单,剩下7为最大值为111 1111即127,那么二进制取反即互补,7位2进制取反即为对总和127取互补数,比如76去掉符号位(100 1100)取反即为51(011 0011),76+51=127(111 1111)
而补码最高位视为-128,-128+51+1即为-76。
所以8位补码实际计算为-128 + (127+1 - a) = -128 + (127 - a) + 1,其中(127 - a)即为取反,加一也由此而来。
另外第8位为1表示范围为-128(1000 0000)~ -1(1111 1111),而后面7为范围为0~127,为了表示范围对齐肯定是要加1的。
现在我们知道了8为有符号数怎么来的,下面我们回到原题,比较8位无符号数大小(通过作差)
回到式1:b-a = b + (-a) = b + (-256 + (255 - a)) (这里没有考虑补码的加一)
实际这里就是将8位无符号数视为9位有符号数比较,那么-256代表第9位的1,剩下要看的为
255-a+b,即b-a = b + (-a) = -256 + ((255 - a) + b) >0? <0? =0?
其中(255-a)为a的相反数,所以这里如果255-a+b存在进位,表明他俩的和一定大于256即他俩和减去1一定大于等于256(注意这两个说法,一个大于一个大于等于,所以我们不用考虑+1,只看进位),即整个式子-256后肯定>0即 b > a, 第二个数严格大于第一个数,反之小于等于!
这样我们就通过9为有符号数判断了8为无符号数的比较,并且解释了为什么只用取反相加看进位,
因为进位表示了是否大于256!