计算机数据的二进制编码(整数)

来源:互联网 发布:冒险岛v矩阵升级 编辑:程序博客网 时间:2024/04/30 05:17

世界上有两种人,懂和不懂二进制的。最近发现自己之前算是不懂的。

一、整数表示

      假设整数数据类型是W位,则写成二进制位x[Xw-1,xw-2,……x0]

1.    无符号整数

对于无符号整数没有符号位,所以上述二进制向量x所表示的无符号整数就是

               

例如W=4时,[1010]就是1*23 +0*22 +1*21+0*20=8+0+2+0=10

2.有符号数

当作为有符号数时,最高有效位Xw-1 称为符号位,解释为负权,

所表示的有符号数就是

例如W=4时,[1010]就是-1*23 +0*22 +1*21+0*20=-8+0+2+0=-6

2.1Xw-1 0时,表示为一个正数,与无符号整数相同。

2.2Xw-1 1时,表示为一个负数,因为这个负权值是-2w-1 2w-1的无符号表示就是(10……0,1后面跟w-10,所以它的绝对值大于任意的组合,所以此时的B2Tw( x)一定是一个负数,

二、C中的整数转换

c语言中,无符号数和有符号数的转换,原则上是基本的位表示保持不变。

这里之所以说是在C语言中,因为在翻译为汇编后,汇编语言则是纯粹的位操作,没有像C语言这样具有符号概念。

转换包括显示或者隐式转换,注意这里的“位表示”表示不变!!

例如int x=0xA

unsigned int ux1=x

unsigned int ux2= (unsigned in)x;

执行完成后 ux1 ux2 均是0xA,

C中如果一个表达式包含有符号和无符号数,那么C会将有符号数强制转换为无符号数,这一点非常重要,

例如表达式-6<0U,返回值是0,因为这里会将这个表达式作为无符号处理,-1,0xA,而作为无符号则是10

三、扩展与截断

      1.扩展,

      分为零扩展和符号扩展。

      2位的数字 (102 扩展成四位时,

      零扩展只是简单的在开头添加0,对于无符号数就是这样扩展为0010

      符号扩展则是在开头添加原来最高位的值,对于有符号数就是这样扩展的1110

      例如i386 linuxc语言

      TYPE c=0xFF;

      int x=c;

      unsigned int ux=c;

TYPEchar时,xux均为0xFFFFFFFF,汇编格式均使用了movsbl

TYPEunsigned char时,xux均为0x000000FF,汇编格式均使用了movzbl

所以在 = 扩展时,gcc编译器根据等号右边操作数的属性,决定如何扩展存入左边操作数所在的存储器。

可以考虑TYPEchar时,unsigned int ux= (unsigned char)c;ux的值~~

2.截断

截断则注意一个原则,截断剩下的位向量保持不变,

[Xw-1,xw-2,……x0]截断为一个k位时,得到一个位向量 [Xk-1,xk-2,……x0]

四、整数运算

      大多数计算机中,无论是有符号还是无符号,除了右移操作和特殊的算术操作即双操作数乘除法指令,

      在翻译成的汇编代码中加减乘除和左移都是一样的指令,右移则根据操作数是否有符号选择算术还是逻辑右移。

整数运算最麻烦的也许就是对溢出的理解了。

1.    加法,

记住有符号和有符号使用用一种算术指令。

因为二进制补码和无符号加法运算有着完全相同的位级表示,而且通过模数加法的属性,可以证得。

1.1无符号

考虑两个无符号数uxuy;两者之和是sum

如果sum超过了unsigned-1),-1的二进制向量位全为1,也就是无符号的最大表达值。

由于我们这种二进制表示有一种环属性,

当超过这个unsigned-1)时,由计算机得到的结果是sum- 2w

1.2有符号

它存在两种溢出,正溢出和负溢出。

有符号数最大值是01……1,即2w-1 -1

有符号数最小值是10……0,即-2w-1

负溢出会是结果成为正,正溢出会是结果成为负。

两个有符号数xysum

如果sum>=2w-1 则正溢出,计算机结果是sum-2w

如果sum<-2w-1 则溢出,计算机结果是sum+2w

 

2. 乘法

   同样二进制补码和无符号乘法运算有着完全相同的位级表示

因为W位的二进制数,成绩结果可能需要超过W位到2W位的位级表示

但是在计算机乘法运算中,将结果截断为W位,所以会在某些大数乘积运算时差生溢出。

例如IA32 linux

int x=0xFFFF;

int y=0xFFFF;

x*y结果则是0xFFFE001,差生一个负数。

因为在大多数及其上,乘除指令相当的慢,需要更多的时钟周期,所以对于带有常数因子的运算,编译器会试着用移位和加法运算的组合来代替。

 

 

ps:

1.表达式的输入好麻烦 

2.二进制表示整数以及运算还有着很多特别的属性,当然都能从以上推导出来,

3.如果希望更深入的理解二进制,可以去看些汇编代码会更好。

原创粉丝点击