技术文档当前位置:秒速牛牛 > 技术文档

原码、补码、反码、移码之间的关系

之前一直搞不明白计算机中负数该如何存储,涉及到负数的问题,想起以前关于负数补码的知识看过但没通透,今天把它弄明白。看了些补码的知识,摘抄了些,自己整理了些。

顺便带着两个小问题:

INT_MAX = 2147483647 ;

cout<<INT_MAX+1<<endl; //正确结果为-2147483648

UINT_MAX = 4294967295;

cout<<UINT_MAX+1<<endl; //正确结果为0

开始正文:

1、负数在计算机中如何表示?

举例来说,+8在计算机中表示为二进制的1000,那么-8怎么表示呢?

很容易想到,可以将一个二进制位(bit)专门规定为符号位,它等于0时就表示正数,等于1时就表示负数。比如,在8位机中,规定每个字节的最高位为符号位。那么,+8就是00001000,而-8则是10001000。但是,随便找一本《计算机原理》,都会告诉你,实际上,计算机内部采用2的补码表示负数。

2、什么是2的补码?

它是一种数值的转换方法,要分二步完成:

第一步,每一个二进制位都取相反值,0变成1,1变成0。比如,00001000的相反值就是11110111。

第二步,将上一步得到的值加1。11110111就变成11111000。

所以,00001000的2的补码就是11111000。也就是说,-8在计算机(8位机)中就是用11111000表示。

不知道你怎么看,反正我觉得很奇怪,为什么要采用这么麻烦的方式表示负数,更直觉的方式难道不好吗?

3、为什么要用2的补码

首先,要明确一点。计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。

2的补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。

还是以-8作为例子。

假定有两种表示方法。一种是直觉表示法,即10001000;另一种是2的补码表示法,即1 1111000。请问哪一种表示法在加法运算中更方便?随便写一个计算式,16 + (-8) = ? 1 0001000 取反 1 1110111    加1    +1 = 1 1111000   再取反  1 0000111  + 1  = 1 0001000 取反不不包括符号位两次取反得到原值正数的补码是其本身 负数的补码是符号位不变 其他位取反之后加1  连着变换两次相当于没有做任何操,16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:                                                        

00010000                                                                                                                                

+10001000

---------

10011000

可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电路。

现在,再来看2的补码表示法。

00010000

+11111000

---------

100001000

可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8) 的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。

综上,对刚开始的两个小问题的解释:

(1)32位系统里,int的最大值为01111111 11111111 11111111 11111111,加1之后为

10000000   00000000   00000000   00000000。这个数是什么?

首先这是个负数-->负数在计算器里都是补码形式存放-->这是个补码-->那么真值是?--> -2147483648(已知负数的补码求该负数,不会求的百度一下吧。。。)

(2)再取反就得到原来的值,对于unsigned,最大值(32个1)加1后最前面的1自然丢失,剩下32个0,所以就是0。

结束。

负数的原码,除了符号位之外,其他位都取反,再加1就是补码。
所以,将补码减去1,再使得除了符号位(第一位)的所有位数取反,得到的就是原码。

比如(字长为8时):
-1的原码是:10000001,除了第一个符号位的1不变,其他位取反得
-1的反码是:11111110,然后再加1得
-1的补码是:11111111。

更多码,如下图

原码、补码、反码、移码之间的关系

CATEGORIES

分类导航

咨询热线

021-51095123

联系人:王先生

手 机:13761987446

邮 箱:xuxinpower@126.com

地 址:上海市嘉定区吴杨东路333号

用手机扫描二维码关闭
二维码
荣鼎彩注册 秒速赛车官方网站 荣鼎彩网站 秒速赛车官方网站 秒速赛车官方网站 秒速牛牛登陆 荣鼎彩登入 75秒赛车官网 荣鼎彩官方网址 荣鼎彩是真的吗