在程序设计语言里,我们会把数据分为各种各样的类型,为什么会有数据类型之分呢?计算机中,所有的数据都会表示成二进制数的形式,对于同样的一个二进制数,数据类型不同,它表示的数据就是不同的。也就是说,同样的一个二进制数。我们可以把它”翻译“成不同的数。
使用一个数据类型的数据的时候,需要注意的问题大概有以下几种:(1)数据溢出
(2)精度问题
(3)强制转换
(1)数据溢出
#include <stdio.h> int main() { char d = 255; printf("%d",d+1); return 0; }
这段代码的输出为0,其实原理很简单。char类型的数据相当于1个字节的无符号整形,即char型数据的范围是00000000~11111111,相当于十进制里的0~255。
程序中的d是char型数据的最大值,给d加1后,d = 100000000(二进制),由于d是char型数据,所以最高位的1会被计算机丢掉。
因此,d = 00000000(二进制),即 d = 0;转化为int型数据后,值依旧是0。
(2)精度问题
#include <stdio.h> int main() { float a = 0.1; for(int i = 0;i < 100;i++){ a += 0.1; } printf("%f",a); return 0; }
运行这段代码,结果可能会有点出人意料。printf函数打印的结果是
我们的代码是没有问题的,它将100个0.1相加,结果是10。计算机内部的数据是用二进制表示的,十进制永远无法精确的表示1/3(三分之一),正如二进制
永远无法精确的表示0.1,只能是一个无限循环小数。
谈到无限,在计算机内部,资源总是有限的,我们只能用有限的内存来表示数据,所以,不管是什么类型的数据,它都是有范围的,所以,计算机内部不能准
确的表示一些小数,只能将它控制在一定的精度内。所以我们就看到了这样的运行结果。
那么,如何避免这种精度缺失的问题呢,我们可以把小数,当作整数来算,将一个小数适当的放大,把它变成整数。举个例子,0.1*10 = 1,这样,我们就把一
个难以表示的0.1进行了转化,然后对计算结果适当的缩小,就可以得到我们想要的结果。我们可以修改上面程序,像这样:
#include <stdio.h> int main() { float a = 0.1; a *= 10; for(int i = 0;i < 100;i++){ a += 1; } printf("%f",a/10); return 0; }
(3)强制类型转换
简单的概括一下强制类型转换,相对来说,由存储空间小的类型转向存储空间大的类型时,不会发生一些数据溢出,丢失之类的问题,一般来说,危险的转换发
生在存储空间大的类型转换为存储空间小的类型。如double->int,float->int,int->char;
这些时候,程序的结果,往往是出人意料的。
#include <stdio.h> int main() { printf("%u ",unsigned(-1)); return 0; }
运行结果为,是不是有一些出乎意料。我们来分析一下这段代码,int型的-1在计算机内部的表示形式为11111111111111111111111111111111(32个1),在将它转换为unsignefd型数据时,它就会被表示为11111111111111111111111111111111(32个1),
这样的话,结果就成了2^32-1,即4294967295,这也是int型数据的最大值。