原码、反码、移码和补码

原码

也叫【符号 - 绝对值】码

最高位0表示正,1表示负,其余二进制位是该数字的绝对值的二进制位

如果是8位二进制,+1的原码是0000 0001,-1的原码是1000 0001

尽管原码简单易懂,但加减运算复杂、存在加减乘除四种运算从而增加了CPU的复杂度、零的表示不唯一(1000 0000或者0000 0000),因此没在计算机中应用


反码

正数的反码是其本身,负数的反码是在其原码的基础上,符号位不变,其余各个位取反

如8位情况下:

+1:原码0000 0001,反码:0000 0001

-1:原码1000 0001,反码:1111 1110

反码运算不便,也没有在计算机中应用

扫描二维码关注公众号,回复: 17170171 查看本文章

移码

移码表示数值平移n位,n称为移码量

移码主要用于浮点数的阶码的存储


补码(应用在计算机中,用于解决整数的存储)

正数的补码就是其本身,负数的补码是在其原码的基础上,符号位不变,其余各位取反,最后+1(即在反码的基础上+1)

+1的原码是0000 0001,反码是0000 0001,补码是0000 0001

-1的原码是1000 0001,反码是1111 1110,补码是1111 1111


已知十进制求二进制补码:

  1. 求正整数的二进制:除2取余,直至商为零,余数倒着排序

  2. 求负整数的二进制:先求与该负数相对应的正整数的二进制代码(记得正整数符号位是0),然后所有位取反,末尾加1,不够位数时左边补1

    以-1为例(8位数):

    先求出-1相对应的正整数(也就是+1)的二进制代码:0000 0001

    然后所有位取反:1111 1110

    末尾加1:1111 1111

  3. 求零的二进制:全是零


已知二进制补码求十进制

  1. 如果首位是0,则表明是正整数,按普通方法来求

  2. 如果首位是1,则表明是负数。先将所有位取反,末尾加1,所得数字就是该负数的绝对值

    以100 1010为例:

    先将所有位取反:011 0101

    末尾加1:011 0110,转换为10进制是:54

    这个54是绝对值,因此100 1010转为十进制是-54

    如果在8位的情况下,其实也一样:

    100 1010下的8位完整的是:1100 1010(左边补1)

    1100 1010取反:0011 0101

    末尾加1:0011 0110,转换为10进制是:54

    这个54是绝对值,因此8位下的100 1010转为十进制是-54

    如果在32位(也就是常说的4个字节,int类型)的情况:

    100 1010下的32位,要先在前面补29个1:即1111 1111 1111 1111 1111 1111 1111 1100 1010

    取反:0000 0000 0000 0000 0000 0000 0000 0011 0101

    末尾加1:0000 0000 0000 0000 0000 0000 0000 0011 0110,转换为10进制是:54

    这个54是绝对值,因此32位下的100 1010转为十进制是-54

  3. 如果全是0,则对应的十进制数就是0

(0000 0000)2 = (0)10
(0000 0001)2 = (1)10
(0000 0002)2 = (2)10

(0111 1111)2 = (127)10
(1000 0000)2 = (-128)10
(1000 0001)2 = (-127)10
(1000 0002)2 = (-126)10

(1111 1111)2 = (-1)10
值得注意的是:(1000 0000)2,它比较特殊

如果直接去看1000 0000,最高位是1,是负数,其它为0,所以认为这个是十进制下的-0,这也是原码和反码会出现的问题,因为0会出现两种不同的表达方法:(0000 0000)或者(1000 0000)
因此才诞生出补码
按照上述二进制补码转换为十进制的方法:
先取反:0111 1111
然后加一:1000 0000,转换为10进制是128
128是绝对值,因此1000 0000(不要与上面加一后的1000 0000弄混)的十进制是-128

使用原码,则8位的取值范围是[1111 1111 , 0111 1111],即[-127 , 127]
使用补码,则8位的取值范围是[1000 0000 , 0111 1111],即[-128 , 127]

int a = 0x80;
printf("%d\n",a);//输出结果:128
char b = 0x80;
printf("%d\n",b);//输出结果:-128

0x80转成二进制是:1000 0000

对于变量a来说,由于它是整型数,所以占4个字节,也就是32位。32位下的0x80是:0000 0000 0000 0000 0000 0000 1000 0000,最高位的是0,代表正数,因此以十进制输出a的结果就是128

对于变量b来说,由于它是字符型,字符型占1个字节,也就是8位。8位下的0x80是:1000 0000。最高位是1,因此它就这么变成了负数,以十进制输出b的记过就是-128

还有一点要注意的是,尽管上面的代码段在gcc编译器下编译没有警告,但在一些编译器上上面的代码会有警告,比如语句char b=0x80可能会有有警告:truncation from 'const int' to 'char',这是说0x80是整形常量,把整型常量赋给char类型,可能会丢失数据,因为char是1个字节,int是4个字节,把占4个字节的数据赋给占1个字节的变量,前面3个高位字节就会丢失

猜你喜欢

转载自blog.csdn.net/YuanApple/article/details/131790709