float变量与“零值”的比较

news/2024/10/30 13:34:57/

目录

1.问题的引出:

2.解决方案

<1>:自定义精度

<2>:系统提供的精度

3.总结 


1.问题的引出:

浮点数在存储的时候,会存在精度的损失

那么在浮点数进行比较的时候,可不可以使用 == 来进行比较,测试代码如下:

#include<stdio.h>
int main()
{double a = 1.0;double b = 0.1;if ((a - 0.9) == 0.1){printf("hahaha\n");}else{printf("hehehe\n");}return 0;
}

 在我们的认知里,a - 0.9 = 1.0-0.9 = 0.1 即程序运行成功后会输出 hahaha ,那么输出结果为是否为这样呢?

代码运行后的结果为:

得出结论:浮点数在进行比较的时候,绝对不可以直接使用 == 来进行比较


 为什么会产生上述结果呢?在此处我们将 a - 0.9 的值打印出来,同时为了更好更好地进行后续代码分析,我们将 0.1 的值也打印出来,代码为:

#include<stdio.h>
int main()
{double a = 1.0;double b = 0.1;printf("%.50lf\n", a - 0.9);printf("%.50lf\n", b);//保留小数点后50位return 0;
}

代码运行后的结果为:

 在此处我们发现,与我们想象中的并不相同,a - 0.9 != 0.1,佐证了上述比较代码的真实性。

原因是,浮点数在存储的过程中存在精度损失,会导致结果存在细微的差别。


2.解决方案

<1>:自定义精度

在此处需要介绍一个函数 --- fabs (求绝对值函数)

 我们可以自行定义一个精度,只要两浮点数相减的绝对值在我们定义的精度之内,我们就可以判定这两个浮点数相等。

对进行比较的代码稍作修改:

#include<stdio.h>
#include<math.h>
#define EPS 0.00000000000001
int main()
{double a = 1.0;double b = 0.1;if (fabs((a - 0.9)-0.1) < EPS){printf("hahaha\n");}else{printf("hehehe\n");}return 0;
}

 程序运行的结果为:

 我们可以看出,此时的输出结果为 hahaha ,不在为 hehehe 。

<2>:系统提供的精度

 系统提供的精度为 --- DBL_EPSILON , 我们将其转到定义可以看到:

                               --- FLT_EPSILON

 

 XXX_EPSILON 是最小误差 --- 即:XXX_EPSILON + n 不等于 n 的最小正数

有很多数字 + n 都可以不等于 n 但是  XXX_EPSILON 是最小的。

对比较的代码进行变化,得出下列代码:

#include<stdio.h>
#include<float.h>
#include<math.h>int main()
{double a = 1.0;double b = 0.1;if (fabs((a - 0.9) - 0.1) < FLT_EPSILON){printf("hahaha\n");}else{printf("hehehe\n");}return 0;
}​

运行结果为:

我们可以看出,此时的输出结果为 hahaha ,不在为 hehehe 。

3.总结 


 float 变量与 0 比较,只需要比较是否在精度范围内。

if (fabs((a - 0.9) - 0.1) < DBL_EPSILON) 可近似看作 if(fabs(x) <  DBL_EPSILON)

思考,在此处是否可以改为 <= ???

fabs(x)=DBL_EPSILON;

即 double y + x != y; // x  为精度 --- 引起数据变化的最小值。

参考: 0 的定义 ---  y + 0.0 = y;

我们可以得出,fabs(x) <=  DBL_EPSILON(确认是否为0的逻辑),如果 = , 就说明 x 本身已经能够引起其他和它+-的数据本身的变化了,不符合0的概念。

不可以添加等号(=)。


 


http://www.ppmy.cn/news/230796.html

相关文章

高性能软件负载OpenResty介绍和安装

目录 1 OpenResty介绍1.1 Nginx 的流程定义1.1.1 流程详解1.1.2 OpenResty处理流程 2 Openresty安装2.1 yum安装2.1.1 添加OpenResty仓库2.1.2 安装OpenResty 2.2 源代码编译安装2.2.1 安装编译环境2.2.2下载最新版源码2.2.3下载缓存插件2.2.4 编译OpenResty2.2.5 安装OpenRest…

宝安西乡产业园变九年制学校,新增宅地、商地。

6月5日&#xff0c;宝安区城市更新和土地整备局发布《西乡街道盐田社区银田地块土地整备利益统筹项目土地整备规划&#xff08;草案&#xff09;》&#xff08;以下简称草案&#xff09;。 草案显示&#xff0c;该项目经过调整后&#xff1a; ● 新增一块二类居住用地&#xf…

访问swagger报错404(1)

本次我的报错原因&#xff1a;idea缓存 报错信息&#xff1a; 解决方案&#xff1a; 1.双击idea右侧maven中的clean清除 2.然后重新运行服务。&#xff08;建议在访问swagger之前最好把浏览器缓存也清理一下。&#xff09; 3.访问swagger

联想M7216NWA墨粉清零:

联想M7216NWA墨粉清零&#xff1a; 在设备就绪状态下&#xff0c;按“功能”键&#xff0c;进入设置菜单&#xff0c;按上下键进行选择&#xff0c;屏幕出现“设备信息”项时按"确认"键&#xff0c;再按上下键选择&#xff0c;当屏幕出现“重置硒鼓”后长按“确认”键…

UBUNTU18.04系统安装打印机

本文以ubuntu安装打印机Lenovo-M7216NWA为例&#xff0c;介绍打印机安装步骤&#xff01; 成功安装的打印机有“位置”参数。如果没有位置参数&#xff0c;则无法打印。 安装步骤如下&#xff1a; 1.打开设置图标 2.选择“设备 > 打印机”打开打印机配置页面。 3. 如上图…

【STM32学习】——定时器输入捕获(IC)PWMI模式频率测量方法主从触发模式IC模式测频/PWMI模式测频率及占空比

文章目录 前言一、输入捕获&#xff08;含PWMI模式&#xff09;二、频率测量三、主从触发模式1.主模式2.从模式3.触发源选择 四、实操案例1.输入捕获模式测频率2.PWMI模式测频率和占空比 总结 声明&#xff1a;学习笔记根据b站江科大自化协stm32入门教程编辑&#xff0c;仅供学…

【数理统计】学习笔记05:区间估计

前文回顾&#xff1a;点估计的优良性及其评选标准 文章目录 一、区间估计定义二、区间估计解题方法2.1 正态总体2.2 比率参数2.3 各分布置信区间汇总 三、例题3.1 单正态总体参数3.2 双正态总体参数3.3 比率参数3.4 单侧置信上/下限 一、区间估计定义 置信区间&#xff1a;设…

JAVA——实现珠峰问题

题目&#xff1a;珠峰问题 分析以下需求&#xff0c;并用代码实现&#xff1a;while 1.珠穆朗玛峰高度为8848米&#xff0c;有一张足够大的纸&#xff0c;厚度为0.0001米。 2.请问&#xff0c;我折叠多少次&#xff0c;可以折成珠穆朗玛峰的高度。 代码一&am…