原码,反码,补码与模

// 示例0
uchar a = 0;
while (1)
{
    a++;
}

  执行上面的代码,记录a的取值将会得到这样的结果: 0,1,2,……,255,0,1,2,……

  我们发现255之后紧跟的是0。从二进制来看就是说[1111 1111]加1之后的结果是[0000 0000]。学习过数字电路加法器的同学并不会觉得有什么不妥。代码中的这一现象就是数字电路的特点决定的。

  我们生活中也有类似这样的例子。时针的取值在1到12之间循环,也可以认为是在0到11之间循环,更符合编程和数学习惯。

  上面两种情况都可以用一个数学工具来刻画——。简单来说,给定一个正整数N作为模,对于任意一个整数n对N取模,就是加上或者减去若干个N,使其落在0到N的范围内。举两个例子,我们给定N=13,56对13取模就是56 - 4 * 13 = 3,-17对13取模就是(-17) + 2 * 13 = 9。不管n取什么值,对13取模的结果只能是0到12之间。


  接下来研究整数在内存中是如何表示的,先来看几个基本数据类型:

数据类型字节数范围
uchar10~255
char1-128~127
short2-32768~32767

每一种数据类型都是由固定长度的二进制组成,表示一定范围的整数。uchar和char都是一个字节长度,表示256个整数,不同的是uchar表示的都是正数,char表示的有正有负。

// 示例1
uchar a = 3;
uchar b = 254;
uchar c = a + b;

// 示例2
char a = 3;
char b = -2;
char c = a + b;

  上面分别是两个类型的加法运算,如果输出结果你会发现两个示例c的结果都是1。结合下面一张表来分析

uchar二进制编码char
30000 00113
20000 00102
10000 00011
00000 00000
2551111 1111-1
2541111 1110-2
2531111 1101-3
2521111 1100-4

观察可以发现,两个示例中的变量a,b,c对应的二进制编码完全一致。也就是说两个示例在计算机内部本质上并无二致。

  仔细想想,其实也好理解。由于计算机遵循着模的运算,-2对256取模的结果是254,而3加254再对256取模的结果是1。uchar和char只是人为做出的规定,一个全部表示正数,一个既有正数也有负数,就像物理中选择了不同的参考系,看问题的角度不同而已。所以uchar和char的类型强制转换也只是切换参考系而已。


  现在我们正儿八经开始讲原码,反码和补码。我们以-2为例

原码反码补码
1000 00101111 11011111 1110

可以看的出来-2的补码和我们上面表中的编码是一致的。书上也说了,计算机中就是补码的形式。

Q: 既然这样,干吗还弄个原码和补码出来?
A: 看看原码和补码,哪个更容易联想到-2?

  显然忽略最高位,原码就是2,最高位1表示负数的话,整个原码就是-2了。而补码则有点费劲。原码,反码到补码其实提供了一种计算机器码的方法。
1. 最高位始终用1表示负数,低七位表示绝对值,就形成了原码。
2. 原码 ===高位保持不变,其他位取反===> 反码 。
3. 反码===加1===>补码。
所以,反码完全沦为一个过渡。这里-128无法使用这一方法得到补码,因为我们无法只用7位为128编码。

Q: 为什么这么算就能得到机器码?巧合?
A: 我们先放一放这个问题,等下再讲。先讲另外一个计算机器码的方法。

  我们再来看254和-2,前面已经讲过-2对256取模的结果就是254,在uchar下254的编码就是char下-2的编码。所以-128到-1的负数加上256得到正数(就是对256取模)在uchar下的编码就是所要求得char类型的机器码。是不是这种方法更本质更自然更简洁一点呢?而且还不遗漏-128。

  回过头来看上面的问题,原码到反码再到补码,其实也可以从数学上得到解释。1000 0010低七位取反加1相当于(1111 1111 - 0000 0010) + 0000 0001= 1111 1110即255-2+1=-2+256=254。(注意:取反可以演变为加法,0101 1010取反=1111 1111 - 0101 1010 = 1010 0101)

  以上观点是阅读他人成果加上自己思考的产物,难免有所偏颇,欢迎各位批评指正。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值