文章目录
前言
在平时的编写代码的过程中,细心的小伙伴们不难发现浮点数的精度的都有些不准确,如下图:
该篇文章将讲解如应对这种问题。
一、浮点数与0的比较
浮点数在内存中存储,并不想我们想的,是完整存储的,在十进制转化成为二进制,是有可能有精度损失的。
注意这里的损失,不是一味的减少了,还有可能增多。浮点数本身存储的时候,在计算不尽的时候,会“四舍五入”
#include<stdio.h>
#include <stdio.h>
#include <windows.h>
int main()
{
double x = 1.0;
double y = 0.1;
printf("%.50f\n", x - 0.9);
printf("%.50f\n", y);
if ((x - 0.9) == y) {
printf("you can see me!\n");
}
else {
printf("oops\n");
}
system("pause");
return 0;
}
正常应该打印“”you can see me!“”,但实际两数并不相等,因为浮点数精度有缺失。
结论:因为精度损失问题,两个浮点数,绝对不能使用==进行相等比较.
那么两个浮点数该如何比较呢?
应该进行范围精度比较
//伪代码
if((x-y) > -精度 && (x-y) < 精度){
//TODO
}
//伪代码-简洁版
if(fabs(x-y) < 精度){ //fabs是浮点数求绝对值
//TODO
}
精度:
自己设置?后面如果有需要,可以试试,通常是宏定义。
使用系统精度?暂时推荐
#include<float.h> //使用下面两个精度,需要包含该头文件
DBL_EPSILON //double 最小精度
FLT_EPSILON //float 最小精度
//代码调整后
#include <stdio.h>
#include <math.h> //必须包含math.h,要不然无法使用fabs
#include <float.h> //必须包含,要不然无法使用系统精度
#include <windows.h>
int main()
{
double x = 1.0;
double y = 0.1;
printf("%.50f\n", x - 0.9);
printf("%.50f\n", y);
if (fabs((x - 0.9) - y) < DBL_EPSILON){ //原始数据是浮点数,我们就用DBL_EPSILON
printf("you can see me!\n");
}
else{
printf("oops\n");
}
system("pause");
return 0;
}
//两个精度定义
#define DBL_EPSILON 2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0
*/
#define FLT_EPSILON 1.192092896e-07F /* smallest such that 1.0+FLT_EPSILON != 1.0
*/
XXX_EPSILON是最小误差,是:XXX_EPSILON+n不等于n的最小的正数。
EPSILON这个单词翻译过来是'ε'的意思,数学上,就是极小的正数 ----来自百度 :)
所以最后改正结果如下:
#include <stdio.h>
#include <math.h>
#include <float.h>
#include <windows.h>
int main()
{
double x = 0.00000000000000000000001;
//if (fabs(x-0.0) < DBL_EPSILON){ //写法1
//if (fabs(x) < DBL_EPSILON){ //写法2
if(x > -DBL_EPSILON && x < DBL_EPSILON){ //书中写法
printf("you can see me!\n");
}
else{
printf("oops\n");
}
system("pause");
return 0;
}
注:DBL_EPSILON是最小误差。
总结
感谢大家阅读本文章!。