偏移二进制编码和二进制补码的区别
一、二进制补码
在计算机系统中,数值一律用补码来表示和存储,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。
正整数的补码和源码相同;
0的补码是0;
负数的补码是符号位不变,原码的各位取反,再加1。
1 1000 0000 1111 1111 …… 1000 0001 0000 0000 0000 0001 …… 0111 1111 -2^n -2^n-1 …… -1 0 1 …… 2^n-1 1 0111 1111+1 1000 0000+1 …… 1111 1110+1 0000 0000 0000 0001 …… 0111 1111 1 1000 0000 1000 0001 1111 1111
负数补码表示的范围比原码稍宽,对于整数,范围是:-2^n~2^n-1
以下参考:https://blog.csdn.net/qq_29545231/article/details/78622927
在32位机中定义signed short a =0xeeee;
执行printf(“%d\n”,a),printf(“0x%x\n”,a)的结果分别是什么呢?
signed short a = 0xeeee; printf("%d\n",a); printf("0x%x\n",a);
结果:
-4370 0xffffeeee
0xeeee=1110 1110 1110 1110,是有符号short型,在计算机中,负数是以补码形式存储的,即:符号位不变,原码各位取反加一。
现在已知负数在计算机中的存储的数值(所以变量初始化时用的十六进制,就直接初始化成补码了啊),再求这个值,顺序就反了,先减一再按位取反:
1110 1110 1110 1110——减1——>1110 1110 1110 1101——按位取反——>1001 0001 0001 0010,最高位1是负数,001 0001 0001 0010是4370,所以值为4370。
但是在32位机中,使用printf函数进行输出时都会进行类型隐式转换,转换为4字节的类型。
有符号类型(signed char)无论向有符号类型(int)还是无符号类型(unsigned int)转换,都会按照有符号数的转换规则(高位补符号位)。
无符号类型(unsigned char)无论向有符号类型(int)还是无符号类型(unsigned int)转换,都会按照无符号数的转换规则(高位补0)。
0xeeee是有符号位,高位补1,所以打印输出为:0xffffeeee
若0xeeee非要输出16位,可把变量强制转化:
printf("0x%x\n",(unsigned short)a);
输出结果:
0xeeee
上面的强制转化只为了打印显示,实际值大小变了。
所以对于二进制补码形式的编码,正负过渡不方便时,可以直接用十进制数来过渡。
二、偏移二进制码
把补码的符号位取反就是偏移二进制码。
如16位的数,0x0000是-32768,0x8000是0,0xFFFF是32767,偏移二进制码用十六进制时正负过渡比较方便