前面几章讲了分支、循环和函数几种基本结构本章主要讲解数据类型及表达式本节介绍数据类型的概念和几种简单数据类型的存储格式、取值范围和精度,并通过实例对整数的“反卷”特性进行解读,对浮点数的“不精确表示”特性进行分析,我来为大家讲解一下关于0.333属于什么数据类型?跟着小编一起来看一看吧!
0.333属于什么数据类型
6.1 数据类型前面几章讲了分支、循环和函数几种基本结构。本章主要讲解数据类型及表达式。本节介绍数据类型的概念和几种简单数据类型的存储格式、取值范围和精度,并通过实例对整数的“反卷”特性进行解读,对浮点数的“不精确表示”特性进行分析。
程序设计的目的是为了解决现实问题,程序设计处理的对象是数据。因此数据的采集、表达和存储是程序设计前要先解决的问题。数据是观察和测量的结果,有些要用整数表示,如年、月、日,但是大部分要用实数表示。数据有定量描述和定性描述两类,测量的结果用数值定量描述,有些观察结果只能定性描述,如描述一个人“冷静、客观和幽默”等,这些数据分别称为数值型和非数值型数据。
无论如何,采集的数据在计算机内部全部采有用二进制表示,因此,要存储采集到的数值型数据和非数值型数据都要预先经过编码——即以某种形式变成二进制,才能存到计算机内部。数据类型就是对不同类别的数据的抽象,反映了数据的编码格式、存储的长度及可以参与的运算。C语言预先提供字符型、整型、长整型、单精度浮点型和双精度浮点型等五类简单类型。程序员也可以把这些类型按一定方式任意组合而构造自己需要的类型——自定义类型。
实际上C语言所有简单类型都是数值型,因为字符型数据被看成了只有8比特的最短整型。这样整型数就有了8位的整型char、16位的整型short或short int、32的整型long或int、64位的整型long long等四类。前面我们已经介绍了整型是按照补码存放的,目的是为了把减法运算变成加法运算。正数的补码与原码一样。所谓原码就是整数直接转换成的二进制,反码就是对原码除了符号位以外的每个二进制位进行取反运算——0变1或1变0,反码加1得到补码。如短整型65的原码、反码和补码都是二进制0000000001000001,但是短整型-65的原码是1000000001000001,反码为1111111110111110,补码为1111111110111111。从右至左开始数,每四个二进制对应一个十六进制位,因此-65对应的16进制补码为0xffbf,其中0x表示16进制的前缀。
整数又可分为有符号整数和无符号整数,分别用signed和unsigned来表示。当整数为有符号数时,整数对应的二进制最高(最左)位用来表示符号,为1表示负数,为0表示正数,因此n位二制制数的有符号整数的取值范围是至,如有符号字符型数据取值范围为-128至127,有符号短整型取值范围在-32768至32767之间;当整数为无符号数时,所有位都用来表示数值,取值范围在0至,如无符号字符取值范围在0至255之间,无符号短整型取值在0至65535之间。
C语言中实数用浮点类型表示,分为单精度浮点型float、双精度浮点型double和长双精度浮点型long double实现三种,分别占用存储空间为4字节、8字节和10字节(长度根据编译不同而不同)。浮点型数据不分有符号数和无符号数,而是按照IEEE 754标准保存数据,即:符号位、指数部分、尾数三个部分。所有浮点数符号位只占1位。float型数据的指数部份为8位,尾数部分为23位;double型数据的指数部份为11位,尾数部分为52位。所以,float数据的取值范围在至之间,double型数据的取值范围为)至之间。float型数据的精度为7位,double型数据精度为16位。
搞清楚整数的取值范围和浮点数的精度对于程序设计是非常重要的,如以下程序:
#include <stdio.h>
int main( )
{
short int a=32767;
a=a 1;
printf("%d",a);
return 0;
}
运行后会是什么结果呢?我们会想当然认为32767 1后结果是32768,但是显示的却是-32768。为什么呢?这是因为短整型数据只有16比特。32767对应的二进制为0111111111111111,加上1后,变成了1000000000000000。最高位变成了1,即此数变成了负数,此数是多少呢?
先看一下-32767的原码、反码和补码:
原码是1111111111111111
反码是1000000000000000
补码是1000000000000001
再来看一下-1的原码、反码和补码:
原码是1000000000000001
反码是1111111111111110
补码是1111111111111111
所以
-32768==
=
=
=
=
=
即对应的数为-32768、对应的无符号整数为32768。即无符号整数32768有符号整数-32768是同一个数。
我们把上述情况称为整数“反卷”,这是由计算机内规定整数位数(如短整型为16位)决定的。当然,如果我们让-32768再减1,结果也会“反卷”到最大值32767,大家可以手算一下。
因为“反卷”,所以以下程序的循环会是死循环吗?
#include <stdio.h>
int main( )
{
short int a=1;
while(a>0){
printf("%d\n",a);
a=a 1;
}
return 0;
}
程序中,a的初值为1,然后每执行一次循环a的值就加1。看起来a是一直是大于0的数,但是事实是当a=32767并输出后,a再加1变成了-32768,此时循环条件不满足,循环就束了。
除了“反卷”外,整数的取值范围也是要注意的问题,如想保存n!。短整型最多可以保存7!,短整型计算8!显示结果是一个负数。我们可以改用长整型long保存阶乘,但能保存的最大阶乘只是16!。还可以用long long来保存阶乘,此时可以保存的最大阶乘也只是20!。如果要保存更大的阶乘,可以使用双精度浮点型double来保存。
浮点数的取值范围虽然很大,但是精度却是有限的。如以下程序说明float与double的精度情况:
#include <stdio.h>
int main( )
{
float a;
double b;
a=123456789;
b=123456789012345678;
printf("a=%.0f,b=%.0lf\n",a,b);
return 0;
}
程序的输出结果是:
a=123456792,b=123456789012345680
可以看到a的值只有前7位是正确的,第8位进行四舍五入,第9位是一个拉圾数据;b的值前16位是正确的,第17位进行四舍五入,第18位是一个拉圾数据。可见,浮点数表示数的范围虽然很大,但是精度并不高。
浮点数还有一个致命的弱点,即不能精确表示小数,即使保存0.1也是有误差的。我们来猜一下以下程序段显示什么?
#include <stdio.h>
int main( )
{
float b;
b=0.1;
if(b==0.1)
printf("b==0.1");
else
printf("b!=0.1");
return 0;
}
根据我们的经验,b是0.1,所以if语句的条件表达式b==0.1为真,所以应该显示“b==0.1”。但是运行结果却与我们预想的不同,显示的是“b!=0”.1。为什么呢?看以下程序:
#include <stdio.h>
int main( )
{
float b;
b=0.1;
printf("%.10f\n",b);
printf("%.10f\n",0.1);
return 0;
}
程序执行后显示结果为:
0.1000000015
0.1000000000
原来常量0.1是双精度浮点数,b是单精度浮点数。在比较时b要转换成双精度浮点数,因此才有b与0.1不等的情况。所以浮点数的比较可采用两个浮点数相减的绝对值与某个很小的正小数比较,如果小于可以认为两者相等。如:
fabs(b - 0.1)<1e-6
可以用来表示b与0.1是否相等。
本节介绍了数据类型的概念及几种简单类型的存储格式,讲解了整数的“反卷”特性及浮点数的相等比较操作。这些都会对正确理解和编写程序起到非常重要的作用。本节就讲到这里,下次再见!
,