15.C language float

First, the concept of floating point numbers

Also known as fractional or floating-point real number. For example, 0.0,75.0,4.023,0.27, -937.198 are legitimate decimals.

C language used to define float and double keywords decimal, float called single-precision floating-point, double precision floating-point referred to, Long
double longer double precision floating point.

(E.g., 1.0 to 2.0 at any interval
between) there are infinitely many real numbers, the computer can not represent all floating point value within the interval.

Second, the point with the case of memory

Let's test the number of bytes float, double and long double three kinds of memory-intensive floating-point data types.

Example (book71.c)

/*
 * 程序名:book71.c,此程序测试float、double和long double占用内存的字节数
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>

int main()
{
  printf("sizeof float is %d\n",sizeof(float));
  printf("sizeof double is %d\n",sizeof(double));
  printf("sizeof long double is %d\n",sizeof(long double));
}

running result

Here Insert Picture Description

Third, the floating point precision

Standard C, float type must represent at least six significant digits, and the range is at least 10 -37 ~ 10 +37 .

type type float and double the minimum value in the same range, but must be able to represent at least 10 significant digits.

long double, in order to meet higher than the double precision type. However, C can only guarantee Long
double type at least the same type of double precision.

Read the above paragraph, it is estimated we are a bit dizzy, integer in the previous section, long occupied by more than int memory, the greater the value of the stored data and an accurate range, however, why the various floats points value of how to store data so vague it? I will not explain why, floating-point storage complex, not yet discussed, first with several programs to test their characteristics.

1, a float test

Example (book73.c)

/*
 * 程序名:book73.c,此程序测试float的特征
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h> 

int main()
{
  float ff2=9.9;   // 测试2位的浮点数
  printf("ff2=%f\n",ff2);
  if (ff2==9.9) printf("ff2==9.9\n");

  float ff5=99.999;   // 测试5位的浮点数
  printf("ff5=%f\n",ff5);
  if (ff5==99.999) printf("ff5==99.999\n");

  float ff6=999.999;   // 测试6位的浮点数
  printf("ff6=%f\n",ff6);
  if (ff6==999.999) printf("ff6==999.999\n");

  float ff7=9999.999;   // 测试7位的浮点数
  printf("ff7=%f\n",ff7);
  if (ff7==9999.999) printf("ff7==9999.999\n");

  float ff8=99999.999;   // 测试8位的浮点数
  printf("ff8=%f\n",ff8);
  if (ff8==99999.999) printf("ff8==99999.999\n");
}

running result

Here Insert Picture Description

Run the program from the two features we can see that the number of float:

1) float data type is expressed by an approximate number, is not accurate, n is erroneous bits after the decimal point, the greater the number of bits of the floating-point number, the greater the error, to 8, when the error is 1, not substantially used.

2) a "==" to compare two integers or characters are equal, however, seems to equal two floating point numbers is not equal.

2, a double test

Example (book74.c)

/*
 * 程序名:book74.c,此程序测试double的特征
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h> 

int main()
{
  double ff2=9.9;   // 测试2位的浮点数
  printf("ff2=%lf\n",ff2);
  if (ff2==9.9) printf("ff2与9.9相等。\n");

  double ff12=999999999.99;   // 测试12位的浮点数
  printf("ff12=%lf\n",ff12);
  if (ff12==999999999.99) printf("ff12与999999999.999相等。\n");

  double ff13=9999999999.99;   // 测试13位的浮点数
  printf("ff13=%lf\n",ff13);
  if (ff13==9999999999.99) printf("ff13与9999999999.999相等。\n");

  double ff14=99999999999.99;   // 测试14位的浮点数
  printf("ff14=%lf\n",ff14);
  if (ff14==99999999999.99) printf("ff14与99999999999.999相等。\n");

  double ff15=999999999999.99;   // 测试15位的浮点数
  printf("ff15=%lf\n",ff15);
  if (ff15==999999999999.99) printf("ff15与999999999999.999相等。\n");

  double ff16=9999999999999.99;   // 测试16位的浮点数
  printf("ff16=%lf\n",ff16);
  if (ff16==9999999999999.99) printf("ff16与9999999999999.999相等。\n");

  double ff17=99999999999999.99;   // 测试17位的浮点数
  printf("ff17=%lf\n",ff17);
  if (ff17==99999999999999.99) printf("ff17与99999999999999.999相等。\n");

  double ff18=999999999999999.99;   // 测试17位的浮点数
  printf("ff18=%lf\n",ff18);
  if (ff18==999999999999999.99) printf("ff17与99999999999999.999相等。\n");
}

running result

Here Insert Picture Description

Run the program from the two features we can see that the number of double:

1) Expression of double data type is an approximation of the number, it is not accurate, n is erroneous bits after the decimal point, the greater the number of bits of the floating-point number, the greater the error, to 17 when the error is 1, not substantially used.

2) "==" double compare two values ​​are equal.

3, the test long double type

Example (book75.c)

/*
 * 程序名:book75.c,此程序测试long double的特征
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h> 

int main()
{
  long double ff2=9.9;   // 测试2位的浮点数
  printf("ff2=%Lf\n",ff2);
  if (ff2==9.9) printf("ff2与9.9相等。\n");

  long double ff12=999999999.99;   // 测试12位的浮点数
  printf("ff12=%Lf\n",ff12);
  if (ff12==999999999.99) printf("ff12与999999999.999相等。\n");

  long double ff13=9999999999.99;   // 测试13位的浮点数
  printf("ff13=%Lf\n",ff13);
  if (ff13==9999999999.99) printf("ff13与9999999999.999相等。\n");

  long double ff14=99999999999.99;   // 测试14位的浮点数
  printf("ff14=%Lf\n",ff14);
  if (ff14==99999999999.99) printf("ff14与99999999999.999相等。\n");

  long double ff15=999999999999.99;   // 测试15位的浮点数
  printf("ff15=%Lf\n",ff15);
  if (ff15==999999999999.99) printf("ff15与999999999999.999相等。\n");

  long double ff16=9999999999999.99;   // 测试16位的浮点数
  printf("ff16=%Lf\n",ff16);
  if (ff16==9999999999999.99) printf("ff16与9999999999999.999相等。\n");

  long double ff17=99999999999999.99;   // 测试17位的浮点数
  printf("ff17=%Lf\n",ff17);
  if (ff17==99999999999999.99) printf("ff17与99999999999999.999相等。\n");

  long double ff18=999999999999999.99;   // 测试17位的浮点数
  printf("ff18=%Lf\n",ff18);
  if (ff18==999999999999999.99) printf("ff17与99999999999999.999相等。\n");
}

running result

Here Insert Picture Description

The test results long double and double the same.

4, test summary

float only express significant figures 6-7 can not use the "==" determines whether the two numbers are equal.

capable of expressing the double-bit valid number 15-16, can be used "==" determines whether the two numbers are equal.

long double double double the amount of memory, but the same expression data precision and double.

In the actual development, the proposed abandoned float, you can only use double, long double time being it is not necessary, but do not know the future of the operating system and compiler if there is improvement in long double.

Fourth, the floating point output

float using% f placeholder.

% lf using double placeholder. The test results prove, double input can not use% f,% f output but can be used, but not recommended% f, because different compilers may differ.

% Lf using long double placeholder noted, L is capitalized.

Floating-point output by default display after the decimal point six.

% Lf using floating point output, the complete output format% m.nlf, the output data specified integer and fractional portions accounted for m bits, n which is the fractional bits. If the length is less than the value m, then fill the spaces left, if the length is greater than the value of m, at the actual number of bits output.

double ff=70001.538;
printf("ff=%lf=\n",ff);       // 输出结果是ff=70001.538000=
printf("ff=%.4lf=\n",ff);     // 输出结果是ff=70001.5380=
printf("ff=%11.4lf=\n",ff);   // 输出结果是ff= 70001.5380=
printf("ff=%8.4lf=\n",ff);    // 输出结果是ff=70001.5380=

Five commonly used library functions

In what follows, I only introduce double, float, and long no longer introduce
knowledge related to double the two data types.

以下是常用的浮点数函数,必须掌握。

double atof(const char *nptr);       // 把字符串nptr转换为double
double fabs(double x);                // 求双精度实数x的绝对值
double pow(double x, double y);      // 求 x 的 y 次幂(次方)
double round(double x);               // double四舍五入
double ceil(double x);                // double向上取整数
double floor(double x);               // double向下取整数
double fmod(double x,double y);      // 求x/y整除后的双精度余数
// 把双精度val分解成整数部分和小数部分,整数部分存放在ip所指的变量中,返回小数部分。
double modf(double val,double *ip);

还有一些数据计算函数,如正弦、对数、指数等,实际开发中极少使用,大家要用的时候再查资料,我就不介绍了。

六、整数转换为浮点数

示例(book77.c)

/*
 * 程序名:book77.c,此程序测试整数与浮点数的转换。
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>

int main()
{
  int ii=3;
  int jj=4;
  double dd;

  dd=ii;        // 可以
  printf("dd is %.2lf\n",dd);

  dd=ii/jj;     // 不行
  printf("dd is %.2lf\n",dd);

  dd=(double)ii/jj;  // 可以
  printf("dd is %.2lf\n",dd);
}

运行效果

Here Insert Picture Description

需要特别注意的是dd=ii/jj这一行代码,dd的值0,不是0.75,有点意外,所以,如果对整数转换为浮点数没有把握,加(double)强制转换是个好办法。关于数据类型的转换,在《C语言数据类型转换》章节中将有更详细的介绍。

七、应用经验

浮点数有一些坑,例如两个浮点数不相等和精度的问题,在实际开发中,我们经常用整数代替浮点数,因为整数是精确的,效率也更高。

例如人的身高一米七五,以米为单位,用浮点数表示是1.75米,如果以厘米为单位,用整数表示是175。

long整数的取值是-9223372036854775808~9223372036854775807,有效数字是19位,而double的有效数字才15-16位,所以,整数可以表达的小数更大的数,更实用,麻烦也更少。

货币:1.75元,如果采用0.01元为单位就是175,采用0.001元为单位就是1750,如果您说要更多小数怎么办?您这是钻牛角尖。

码农之道:高水平的程序员不容易掉坑里,注意,是不容易,不是不会,最好的方法是不要靠近坑。

八、科学计数法

在实际开发中,我们很少使用科学计数法,但是它经常出现在计算机系统中,例如浮点数在内存中的存放方式就是科学计数法,所以我们还是有必要学习科学计数法。

科学记数法是一种记数的方法。把一个数表示成a与10n相乘的形式(1≤|a|<10,n为整数),这种记数法叫做科学记数法。当我们要书写或运算某个较大或较小且位数较多时,用科学记数法免去浪费很多空间和时间。

例如:51400000000=5.14×1011,计算机表达10的幂是一般是用E或e,也就是51400000000=5.14E11或5.14e11。

用科学记数法表示数时,不改变数的符号,只是改变数的书写形式而已,可以方便的表示日常生活中遇到的一些极大或极小的数 。如:光的速度大约是300,000,000米/秒;全世界人口数大约是:6,100,000,000,这样的数书写和显示都很不方便,为了免去写这么多重复的0,将其表现为这样的形式:6,100,000,000=6.1×109,即6.1E9或6.1e9。

0.00001=1×10-5,即绝对值小于1的数也可以用科学记数法表示为a乘10-n的形式。即1E-5或1e-5。

科学计数法采用%e或%E输出,完整的输出格式是%m.ne或%m.nE,指定输出数据整数部分和小数部分共占m位,其中有n位是小数。如果数值长度小于m,则左端补空格,若数值长度大于m,则按实际位数输出。

示例(book78.c)

/*
 * 程序名:book78.c,此程序测试浮点数据的科学计数法。
 * 作者:C语言技术网(www.freecplus.net) 日期:20190525
*/
#include <stdio.h>

int main()
{
  double dd;

  dd=123000000;
  printf("dd is  %.2e\n",dd);

  dd=-123000000;
  printf("dd is %.2e\n",dd);

  dd=0.0000000123;
  printf("dd is  %.2e\n",dd);

  dd=-0.0000000123;
  printf("dd is %.2e\n",dd);
}

运行效果

Here Insert Picture Description

九、课后作业

1)编写示例程序,类似本章节的book71.c、book73.c、book74.c、book75.c、book77.c、book78.c,编译并运行它,程序员是写出来的,不是看出来的,熟能生巧,您每天的付出都有意义。

2)编写示例程序,测试浮点数赋值超过取值范围的后果。

3)关于浮点数在内存中的存储方式,建议大家去百度一下(搜索关键字为C语言浮点数存储方式),了解一下相关的概念。

4)编写示例程序,测试把浮点数赋给整数变量的结果,并思考原因。

5)本题作业建议在学完《C语言数据类型转换》后再做,因为有知识点交叉,重写浮点数的常用库函数,实现其功能,函数的声明如下:

double FABS(const double x);          // 求双精度实数x的绝对值
double ROUND(const double x);         // double四舍五入
double CEIL(const double x);          // double向上取整数
double FLOOR(const double x);         // double向下取整数
// 把双精度val分解成整数部分和小数部分,整数部分存放在ip所指的变量中,返回小数部分。
double MODF(double val,double *ip);  

十、版权声明

C语言技术网原创文章,转载请说明文章的来源、作者和原文的链接。
来源:C语言技术网(www.freecplus.net)
作者:码农有道

如果文章有错别字,或者内容有错误,或其他的建议和意见,请您留言指正,非常感谢!!!

Published 29 original articles · won praise 2 · Views 681

Guess you like

Origin blog.csdn.net/m0_45133894/article/details/104646510