计算机中的原码,反码,补码,以及他们在内存中的存储形式。

1.原码

原码就是早期用来表示数字的一种方式: 一个正数,转换为二进制位就是这个正数的原码。负数的绝对值转换成二进制位然后在高位补1就是这个负数的原码

      举例说明:

      int类型的 3 的原码是 11B(B表示二进制位), 在32位机器上占四个字节,那么高位补零就得:

      00000000 00000000 00000000 00000011

      int类型的 -3 的绝对值的二进制位就是上面的 11B 展开后高位补零就得:

      10000000 00000000 00000000 00000011      

      但是原码有几个缺点,

a.零分两种 +0 和 -0 。

b.在进行不同符号的加法运算或者同符号的减法运算的时候,不能直接判断出结果的正负。需要将两个值的绝对值进行比较,然后进行加减操作,

最后符号位由绝对值大的决定。于是反码就产生了。

2.反码    

正数的反码就是原码,负数的反码等于原码除符号位以外所有的位取反

      举例说明:

      int类型的 3 的反码是

      00000000 00000000 00000000 00000011

      int类型的 -3 的反码是

      11111111 11111111 11111111 11111100

      除开符号位 所有位 取反

      解决了加减运算的问题,但还是有正负零之分,然后就到补码了

3.补码

正数的补码与原码相同,负数的补码为 其原码除符号位外所有位取反(得到反码了),然后最低位加1.

      还是举例说明:

      int类型的 3 的补码是:

      00000000 00000000 00000000 00000011

      int类型的 -3 的补码是

      11111111 11111111 1111111 11111101

      就是其反码加1

总结: 

a.正数的反码和补码都与原码相同。

b.负数的反码为对该数的原码除符号位外各位取反。

c.负数的补码为对该数的原码除符号位外各位取反,然后在最后一位加1  

d.原码好理解了,但是加减法不够方便,还有两个零(正负0)

e.反码稍微困难一些,解决了加减法的问题,但还是有两个零

f.补码理解困难

4.数在内存中都是以补码形式存在的

对于一个负数-x,它的二进制表示(补码)求法如下:

a.对x的原码进行取反运算

b.将取反运算的结果+1

  对于大多数语言来说,char类型的有效范围是-128~127,那么如果我们把128这个超过了char类型表示范围的数赋值给一个char型变量ch,结果会怎样呢?ch的值会变成0,还是其它值?答案是,ch的值会变成-128,因为128超越了最大值127,于是它开始从最小值开始,搜索一个合适的位置。同样的道理,将129赋值给ch,ch的值会变成-127。 

  还有一个原理就是有符号和无符号数据的区别。我们知道,char也分为signed和unsigned两种,前者是默认值,而后者的表示范围是0~255。不管有无符号,这个区间的大小都是256,这也在情理之中,毕竟1个字节由8个位组成,每个位可以取0或1,那么一共就能表示2^8种不同的情况,2^8就是256。
同时,根据上面的理论,我们可以得出,将255赋值给ch,结果是-1。我们可以分别求出255和-1的补码,它们都是11111111。当然,这不是什么巧合,这是有科学道理的。255是unsigned char的最大值,它也是signed char能表示的负数中的最大值。当一个char是unsigned类型的时候,它的第一位自然不会被认为是符号位,所以11111111能表示255,而当这个char是signed类型时,第一位被解析成符号位,结果就是-1了。

c.对绕回和同余的解释

-336的无符号整数是65200呢?书上说是2的补码(书中描述):数字0到32767代表它们本身,而数字32768到65535则代表负数,65535代表-1,65534代表-2,依次类推,因此-336由65536-336,也即65200来表示;

d.同余

很多人并不理解补码。补码就是同余啊。1000000是正128你知道吧,正负128模256是同余的。加减乘可以直接算也是同余的定理决定的,而不是凑出来的巧合,哪可能凑出这种东西?

8位只能表示256个数,0到255,但我还想表示一些负数怎么办呢?就用与该负数同余的正数来表示呗。-1=255,-2=254,等等。

建议脱离算数的思维方式,这其实就是一个环。模任何一个正整数(如256),可以把所有整数分类,比如模256可分256类,0 256 -256...是一类(余0类),1 257 -255...是一类(余1类),等等,这256类可看作环Z_{256}的元素,你看-128和128是同一个类里的(余128类),用一个代表另一个罢了。补码和普通的unsigned integers都是在每类中选一个数,unsigned integers选0到255,补码表示的有符号整数选-128到127,都是一个数恰好对应一个类。

当你明白这一切后,补码就是顺理成章的事。

e.8位有符号数的列表   内存中8位二进制10000000表示 -128

-1<--->11111111   -2<--->11111110   -126<--->10000010   -127<--->10000001   -128<--->10000000 

127<--->01111111   126<--->01111110   125<--->01111101   002<--->00000010   001<--->00000001   000<--->00000000

posted @ 2018-11-18 18:02  浪里飞  阅读(918)  评论(0编辑  收藏  举报