在C语言中,整形的存储和浮点型的存储有着截然不同的方式(这两种存储方式在前面文章已有介绍),但是存放的数据超过了开辟的空间所能存放的数据的大小,整形和浮点型都会出现存储数据的错误。
今天,我来介绍关于浮点型的数据存储的错误,也就是精度损失。
验证浮点数精度损失的存在
#include<stdio.h>
int main ()
{
int a = 1.0;
printf("%.50f",a-0.9);
return 0;
}
由于float类型数据的精度损失,导致了原本应该输出0.1的程序,输出了个与0.1相近的值。
精度损失是否代表数据变小
精度损失,顾名思义,在数据的存储和取出的情况下,数据可能会有所损失,那么损失是否代表着数据变小?为解答该问题,我们重新写另外一个小程序
#include<stdio.h>
int main ()
{
double num = 0.1;
printf("%.50f\n",num);
return 0;
}
观察可以知道,在此次的精度损失下,输出的数据非但没有变小,反而增大。所以精度缺少并不意味着数据的变小,有时候会变大。
关于浮点数在比较方面的问题
由前面可以得知,浮点数的存储存在着精度损失的问题,而这个问题,是否会导致在比较浮点数的大小方面存在误差?同样,还是通过小程序来进行证明:
#include<stdio.h>
int main ()
{
double x = 1.0;
if((x-0.9)==0.1)
printf("you can see me!\n");
else
printf("oops!\n");
return 0;
}
由图片可以发现,由于精度的损失,导致了原本应该打印第一个语句的程序打印了第二个语句。我们不由得思考,由于浮点型的精度损失,导致了浮点型数据在比较过程中可能出现错误的结果,我们应当如何解决该问题呢。
精度的引入
在C语言中,就已经给出了精度,如下:
头文件 : #include<float.h>
DBL_EPSILON ----- double最小精度
FLT_EPSILON ----- float最小精度
C语言中,还存在一个函数,fabs返回参数的绝对值
头文件 : #include<math.h>
由于浮点型精度的损失,导致了浮点型数据在比较时不能直接进行比较,所以采用了精度。如果浮点型数据在可预见的范围内,那么就可以断定该判断的结果为真。如下:
两个float类型的数据x,y
x-y == 0
直接判断不能成立
fabs(x- y) < FLT_EPSILON
如果该结果这个精度的范围内,便可以判断x - y的结果为0;
最后,我们修改一下前面的代码:
#include<stdio.h>
#include<math.h>
#include<float.h>
int main ()
{
double x = 1.0;
if(fabs(x-0.9-0.1) < FLT_EPSILON)
printf("you can see me!\n");
else
printf("oops!\n");
return 0;
}
所以,在以后的浮点型数据的比较下,我们应当使用fabs函数和精度,保证结果的正确性。