整形数据

来源:互联网 发布:电磁炉什么牌子好 知乎 编辑:程序博客网 时间:2024/05/16 00:32

一)整形数据的存储和数值范围

1、计算机使用的是二进制的形式来存储数据,计算机内的存储单元是位(bit),每一位都可以表示1位二进制数(即0或者1),比如8位的存储单元,可以表示的二进制的范围是0000 0000~1111 1111,即十进制的0~255。

2、计算机的内存使用8位(bit)表示一个字节Byte简写B(注意,是大写B,小写b表示的是一位),1KB=1024B,1MB=1024KB,1GB=1024MB。

3、C++对字节的定义有一些不同,有可能是16位表示一个字节,有可能8位表示一个字节,C++字节的多少是依据字符集的位数来确定的,我们使用标准的位数来表示字节,即8位表示一个字节。

4、C++使用不同的内存量来存储整型数据,使用的内存量越大,能存储的数值就越大,比如对于int型,假如使用16位来存储,这时若是无符号的int型,则能表示的值的范围是0~65535(即1111 1111 1111 1111);若是有符号的int型,则能表示的值的范围是-32768~32767,有符号整型时,最高位(就是第1位)表示符号位,0表示正数,1表示负数,因此除去符号位时,int的有效位只有15位二进制,这时15位二进制的最大正值是32767,即0111 1111 1111 1111,而最大负数是-32768,即1000 0000 0000 0000 0000,从以上示例可以看到,无符号整型可以表示更大的整数,但不能表示负数。

5、C++规定的各种整型的最小位数(注意:只规定了最小位数,因此各系统和编译器的长度可能会不一样)

1)、short至少16位;

2)、int至少要与short一样长;

3)、long至少32位,且至少要与int一样长;

4)、long long 至少64位,且至少要与long一样长,注意:long long是新标准,编译器不一定支持;


二)无符号的整形数据溢出处理

1、这里的溢出,指的是数值超过整型类型所能表示的最大值或者最小值,比如对于short int类型的整型,假设使用16位进制存储,则表示的数值范围是-32768~32767,若对short int类型赋予一个比这个范围更大或更小的数,则就产生溢出,比如short int a=32769; 或short int b=-32769;等。

2、C++规定,对于无符号整型从不会溢出,若数值大于或小于无符号整型能存储的最大值或最小值的时候,这时应使用R mod (M+1)即求模运算来作为最终的结果值,其中mod表示的是求模运算(在C++中使用的是符号%来表示求模运算符),求模运算就是两个数相除后的余数作为其值;R表示实际需要存储的数,M表示无符号整数能存储的最大值。比如unsigned short int a=65537;cout<<a<<endl;则输出a的值是1,因为65537mod (65535+1)之后得到的值为1,即65537/65536的余数为1,所以最后a的值为1。注意:C++规定的无符号整数值不会发生溢出情况,并不代表无符号整形数据在运算时能得到正确的结果。比如unsigned short int a=65535; unsigned short int b;  b=a+2; cout<<b<<endl; 输出1,可以看到b的值并不等于65537,因为65537溢出了,需要对65537进行求模运算,最后得到b的值是1。

3、将一个负数赋给一个无符号整型时的情况:这时使用的是与该负数同余的正数来表示其值的,比如对于unsigned short int a=-1;cout<<a<<endl;输出65535,因为-1与65535对模65536是同余的,因此a的值就是65535。

4、为什么-1和65535对模65536是同余的:在〈计算机原理〉关于补码的内容就有讲解,这里我们以数学的方式来讲解这个问题,数学中同余的定义是:如果两个正整数a和b之差能被n整除,那么我们就说a和b对模n同余,记作a≡b (mod n),不难看出-1与65535之差能被65536整除,因此他们是同余的。

5、对于无符号整数溢出时的几种简便理解方法:

1)、理解方法一:不难看出,对于无符号整数,当超出他的范围时,数值会被从另一头开始循环,比如对于无符号短整数而言,正数65536因为超出最大数65535的范围,因此数值将从另一头(最小值开始)循环,其值为0,同理65537就表示1,对于负数也是同样的道理,对于-1,因为超过最小数0,因此从另一头(最大值开始)循环,其值就是65535。

2)、理解方法二:当数值R超出正数的最大范围值M时,将数值R减去最大值M+1,最后得到的值就是数值R的值,当数值R超出负数的最大范围时,则将R加上正数最大范围值M+1所得到的值就是R的值,比如unsigned short int a=-1;  这时a的值就是-1+65536=65535。再如unsigned short int a=65539;其a的值是65539-65535=4;

3)、理解方法三:直接将负数转换为二进制数的补码,再将其转换为对应的无符号10进制值,这个值就是无符号整数溢出时的值;若正数超出长度,则直接将最高位丢弃即可;比如unsigned short int a=-1; 其中-1的二进制形式为1000 0000 0000 0001(共16位),转换为补码就是1111 1111 1111 1111因此结果a的值就是65535,同理unsigned short int a=65536;其二进制就是1 0000 0000 0000 0000,将最高位丢弃,因此a的值就是0。


三)有符号整型数据的溢出处理

1、对于有符号整型C++没有作出规定,也就是说若出现有符号整型产生溢出,则各编译器的处理是不一样的,有些编译器可能还会出错。

2、VC2005对于有符号整数数据溢出时的处理方式与无符号整型数溢出的处理是相同的。

1)、比如short int a=32769;cout<<a<<endl; 输出-32767;下面以3种方式来分析这种数的结果,

2)、方法1:比较容易理解,超出最大值时从另一端开始循环,因为32769超出short int的最大数32767,因此从另一端(最小值)开始循环,输出就是-32767。

3)、方法2:使用求模方式,使用这种方法比较简单,对于16位二进制数的模数是65536(注意:有符号整数与无符号整数的模数是相同的),因此32769-65536=-32767;注意:若是负数超出最大值就应加65536而不是减。

4)、方法3:转换为二进制形式,32769的二进制形式为1000 0000 0000 0001 可知,对于有符号整数来讲,这是个负数,转换为补码就是1111 1111 1111 1110,再转换为有符号的十进制数就是-32767。对于负数超出范围,将其转换为二进制数的补码后,再直接丢弃最高位,最后转换为十进制数即可,比如short int a=-32769;其二进制形式为1 1000 0000 0000 0001,其补码是1 0111 1111 1111 1111 丢弃最高位就是0111 1111 1111 1111再转换为10进制数就是3276