4.3 float、double类型介绍

喜欢ヅ旅行 2023-06-26 08:25 16阅读 0赞

C语言学习栏目目录

目录

4.1 int类型介绍

4.2 char类型介绍

4.3 float、double类型介绍

4.4 小结及其他数据类型简单介绍

4.5 类型大小


  1. 各种整数类型对大多数软件开发项目而言够用了。然而,面向金融和数学的程序经常使用浮点数。C语言中的浮点类型有floatdoublelong double类型。它们与FORTRANPascal中的real类型一致。前面提到过,浮点类型能表示包括小数在内更大范围的数。浮点数的表示类似于科学记数法(即用小数乘以10的幂来表示数字)。该记数系统常用于表示非常大或非常小的数。下表列出了一些示例。

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ0MTEzNDg_size_16_color_FFFFFF_t_70

  1. 1列是一般记数法;第2列是科学记数法;第3列是指数记数法(或称为e记数法),这是科学记数法在计算机中的写法,e后面的数字代表10的指数。C标准规定,float类型必须至少能表示6位有效数字,且取值范围至少是10 -37 10 +37 。前一项规定指float类型必须至少精确表示小数点后的6位有效数字,如33.333333。后一项规定用于方便地表示诸如太阳质量(2.0e30千克)、一个质子的电荷量(1.6e-19库仑)或国家债务之类的数字。通常,系统储存一个浮点数要占用32位。其中8位用于表示指数的值和符号,剩下24位用于表示非指数部分(也叫作尾数或有效数)及其符号。
  2. C语言提供的另一种浮点类型是double(意为双精度)。double类型和float类型的最小取值范围相同,但至少必须能表示10位有效数字。一般情况下,double占用64位而不是32位。一些系统将多出的 32 位全部用来表示非指数部分,这不仅增加了有效数字的位数(即提高了精度),而且还减少了舍入误差。另一些系统把其中的一些位分配给指数部分,以容纳更大的指数,从而增加了可表示数的范围。无论哪种方法,double类型的值至少有13位有效数字,超过了标准的最低位数规定。C语言的第3种浮点类型是long double,以满足比double类型更高的精度要求。不过,C只保证long double类型至少与double类型的精度相同。

1.声明浮点型变量

  1. 浮点型变量的声明和初始化方式与整型变量相同,下面是一些例子:
  2. float noah, jonah;
  3. double trouble;
  4. float planck = 6.63e-34;
  5. long double gnp;

2.浮点型常量

  1. 在代码中,可以用多种形式书写浮点型常量。浮点型常量的基本形式是:有符号的数字(包括小数点),后面紧跟eE,最后是一个有符号数表示10的指数。下面是两个有效的浮点型常量:

-1.56E+12
2.87e-3
正号可以省略。可以没有小数点(如,2E5)或指数部分(如,19.28),但是不能同时省略两者。可以省略小数部分(如,3.E16)或整数部分(如,.45E-6),但是不能同时省略两者。下面是更多的有效浮点型常量示例:

  1. 3.14159
  2. .2
  3. 4e16
  4. .8E-5
  5. 100.
  6. 不要在浮点型常量中间加空格:1.56 E+12(错误!)
  7. 默认情况下,编译器假定浮点型常量是double类型的精度。例如,假设somefloat类型的变量,编写下面的语句:
  8. some = 4.0 * 2.0;
  9. 通常,4.02.0被储存为64位的double类型,使用双精度进行乘法运算,然后将乘积截断成float类型的宽度。这样做虽然计算精度更高,但是会减慢程序的运行速度。在浮点数后面加上fF后缀可覆盖默认设置,编译器会将浮点型常量看作float类型,如2.3f9.11E9F。使用lL后缀使得数字成为long double类型,如54.3l4.32L。注意,建议使用L后缀,因为字母l和数字1很容易混淆。没有后缀的浮点型常量是double类型。
  10. C99 标准添加了一种新的浮点型常量格式——用十六进制表示浮点型常量,即在十六进制数前加上十六进制前缀(0x0X),用pP分别代替eE,用2的幂代替10的幂(即,p计数法)。如下所示:0xa.1fp10十六进制a等于十进制10,.1f1/16加上15/256(十六进制f等于十进制15),p102 10 10240xa.1fp10表示的值是(10 + 1/16 +15/2561024(即,十进制10364.0)。注意,并非所有的编译器都支持C99的这一特性。

3.打印浮点值

  1. printf()函数使用%f转换说明打印十进制记数法的floatdouble类型浮点数,用%e打印指数记数法的浮点数。如果系统支持十六进制格式的浮点数,可用aA分别代替eE。打印long double类型要使用%Lf、%Le或%La转换说明。给那些未在函数原型中显式说明参数类型的函数(如,printf())传递参数时,C编译器会把float类型的值自动转换成double类型。下述程序清单演示了这些特性。
  2. /************************************************************************
  3. 功能:以两种方式显示float类型的值
  4. ************************************************************************/
  5. #include<stdio.h>
  6. int main(void)
  7. {
  8. float aboat = 32000.0;
  9. double abet = 2.14e9;
  10. long double dip = 5.32e-5;
  11. printf("%f 可以写成 %e\n",aboat,aboat);
  12. // 下一行要求编译器支持C99或其中的相关特性
  13. printf("并且它的16进制为: %a \n",aboat);
  14. printf("%f 可以写成 %e\n",abet,abet);
  15. printf("%Lf 可以写成 %Le\n",dip,dip);
  16. system("pause");
  17. return 0;
  18. }

该程序的输出如下,前提是编译器支持C99/C11:(该程序示例演示了默认的输出效果。后续将介绍如何通过设置字段宽
度和小数位数来控制输出格式)

  1. 32000.000000 可以写成 3.200000e+04
  2. 并且它的16进制为: 0x1.f400000000000p+14
  3. 2140000000.000000 可以写成 2.140000e+09
  4. 0.000053 可以写成 5.320000e-05
  5. 请按任意键继续. . .

4.浮点值的上溢和下溢

  1. 假设系统的最大float类型值是3.4E38,编写如下代码:
  2. float toobig = 3.4E38 * 100.0f;
  3. printf("%e\n", toobig);
  4. 会发生什么?这是一个上溢(overflow)的示例。当计算导致数字过大,超过当前类型能表达的范围时,就会发生上溢。这种行为在过去是未定义的,不过现在C语言规定,在这种情况下会给toobig赋一个表示无穷大的特定值,而且printf()显示该值为infinfinity(或者具有无穷含义的其他内容)。当除以一个很小的数时,情况更为复杂。回忆一下,float类型的数以指数和尾数部分来储存。存在这样一个数,它的指数部分是最小值,即由全部可用位表示的最小尾数值。该数字是float类型能用全部精度表示的最小数字。现在把它除以 2。通常,这个操作会减小指数部分,但是假设的情况中,指数已经是最小值了。所以计算机只好把尾数部分的位向右移,空出第1 个二进制位,并丢弃最后一个二进制数。以十进制为例,把一个有4位有效数字的数(如,0.1234E-10)除以10,得到的结果是0.0123E-10。虽然得

到了结果,但是在计算过程中却损失了原末尾有效位上的数字。这种情况叫作下溢(underflow)。C语言把损失了类型全精度的浮点值称为低于正常的(subnormal)浮点值。因此,把最小的正浮点数除以 2将得到一个低于正常的值。如果除以一个非常大的值,会导致所有的位都为0。现在,C库已提供了用于检查计算是否会产生低于正常值的函数。还有另一个特殊的浮点值NaN(not a number的缩写)。例如,给asin()函数传递一个值,该函数将返回一个角度,该角度的正弦就是传入函数的值。但是正弦值不能大于1,因此,如果传入的参数大于1,该函数的行为是未定义的。在这种情况下,该函数将返回NaN值,printf()函数可将其显示为nan、NaN或其他类似的内容。

浮点数舍入错误
给定一个数,加上1,再减去原来给定的数,结果是多少?你一定认为是1。但是,下面的浮点运算给出了不同的答案:

  1. /************************************************************************
  2. 功能:以两种方式显示float类型的值
  3. main1函数:以两种方式显示float类型的值
  4. mian函数:演示舍入错误
  5. 使用方法:需要使用哪个函数就将哪个函数改成main即可。
  6. ************************************************************************/
  7. #include<stdio.h>
  8. int main(void)
  9. {
  10. float a,b;
  11. b = 2.0e20 + 1.0;
  12. a = b - 2.0e20;
  13. printf("%f \n",a);
  14. system("pause");
  15. return 0;
  16. }

该程序的输出如下:

20191231093234435.png

得出这些奇怪答案的原因是,计算机缺少足够的小数位来完成正确的运算。2.0e20是 2后面有20个0。如果把该数加1,那么发生变化的是第21位。要正确运算,程序至少要储存21位数字。而float类型的数字通常只能储存按指数比例缩小或放大的6或7位有效数字。在这种情况下,计算结果一定是错误的。另一方面,如果把2.0e20改成2.0e4,计算结果就没问题。因为2.0e4加1只需改变第5位上的数字,float类型的精度足够进行这样的计算。

浮点数表示法
上一个方框中列出了由于计算机使用的系统不同,一个程序有不同的输出。原因是,根据前面介绍的知识,实现浮点数表示法的方法有多种。为了尽可能地统一实现,电子和电气工程师协会(IEEE)为浮点数计算和表示法开发了一套标准。现在,许多硬件浮点单元都采用该标准。2011年,该标准被ISO/IEC/IEEE 60559:2011标准收录。该标准作为C99和C11的可选项,符合硬件要求的平台可开启。floaterr.c程序的第3个输出示例即是支持该浮点标准的系统显示的结果。

源码下载

不懂可以留言,我看到会回复

发表评论

表情:
评论列表 (有 0 条评论,16人围观)

还没有评论,来说两句吧...

相关阅读

    相关 43 inventory文件

          Ansible可同时操作属于一个组的多台主机,是通过inventory文件配置来实现的,组与主机的关系也是由inventory来定义的。默认inventory文件路

    相关 43. 字符串相乘

    给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。 示例 1: > 输入: num1 = “