【C++】float / double 与 0 值比较

news/2024/5/6 7:37:57/文章来源:https://blog.csdn.net/weixin_44488341/article/details/131646365

【C++】float / double 与 0 值比较

文章目录

  • 【C++】float / double 与 0 值比较
    • 1. 概述不同
      • 1.1 - float 与 double 实际存储
      • 1.2 - C 语言与 C++ 中不同
    • 2. 比较方法
      • 2.1 - C 风格比较
      • 2.2 - 使用 limits 函数
    • 3. 参考链接 References

1. 概述不同


当然使用普通的比较没有问题,如果不考虑精度的话,可以使用

double dvalue = 0.0;
if (0.0 == dvalue)

但是,在某些情况下可能出错。

1.1 - float 与 double 实际存储


floatdouble 在计算机中存储的内容可能与想象中等于代码赋予的字面值不同,如下

float f = 0.1; // f = 0.100000001490116119384765625
double g = 0.1; // g = 0.1000000000000000055511151231257827021181583404541015625

因此与 0 值的比较不可以单纯比较 == 0.0

1.2 - C 语言与 C++ 中不同


然而不仅两种类型不同,单独 double 类型在 C 语言 / C++ 两种语言中也是不同的,比如如下一段代码:

int main ()
{double a = -1.0e-120;if (a < 0.0)printf ("%g < 0\n", a);if (a > 0.0)printf ("%g > 0\n", a);if (a == 0.0)printf ("%g == 0\n", a);
}

使用 gcc 3.3 编译 C 语言,得到的结果为

-1.0e-120 < 0

而使用同一个编译器 编译 C++ ,得到的结果为

-1.0e-120 == 0

2. 比较方法

这里使用 C++ 的方式进行比较

2.1 - C 风格比较


float,double 分别遵循 R32-24 , R64-53 的标准。网上有一些答案判断 float 的精度误差在 ±1e-6 , double 精度误差在 ±1e-15 之间,示例:

#include <cmath>
#include <cstdio>
#define FLOAT_EPSILON 1e-6
#define DOUBLE_EPSILON 1e-15int main(int argc, char* argv[])
{float f = 0.0;double d = 0.0;if (fabs(f) < FLOAT_EPSILON) {printf("float value: %g ,",fabs(f));printf("is equal to zero!\n");} else {printf("float value: %g ,", fabs(f));printf("is not equal to zero!\n");}if (fabs(d) < DOUBLE_EPSILON) {printf("double value: %g ,", fabs(d));printf("is equal zero!\n");} else {printf("double value: %g ,", fabs(d));printf("double not equal to zero!\n");}return 0;
}

判断一个单精度浮点数:if (fabs(f) <= 1e-6)
判断一个双精度浮点数:if (fabs(f) <= 1e-15)
若在正负范围内,表示等于 0 ,否则,不为 0 。

注:必须包含 <cmath> 头文件,Windows 上创建 Visual Studio 工程,在它的外部依赖项中包含了自身的相似的 VC 头文件,但 Linux 下不显式包含会报错。

但我们不必自己去定义这样一个数,可以包含 C 语言的头文件 float.h

#include <cfloat>

头文件中有定义

// smallest such that 1.0+DBL_EPSILON != 1.0
#define DBL_EPSILON      2.2204460492503131e-016 
// smallest such that 1.0+FLT_EPSILON != 1.0
#define FLT_EPSILON      1.192092896e-07F        

最小的增量使得相等判断失效。

DBL_EPSILON 为影响 double 相等比较的最小增量,DBL 表示 double.
FLT_EPSILON 为影响 float 的最小增量 FLT 表示 float.

另有 LDBL_EPSILON 为影响 long double 的最小增量,实际值在 Windows 上与 DBL_EPSILON 一致。

因此代码可以简化为

#include <cmath>
#include <cstdio>
#include <cfloat>
#include <iostream>int main(int argc, char* argv[])
{float f = 0.0;double d = 0.0;if (fabs(f) < FLT_EPSILON) {printf("float value: %g ,",fabs(f));std::cout << "is equal to zero!" << std::endl;} else {printf("float value: %g ,", fabs(f));std::cout << "is not equal to zero!" << std::endl;}if (fabs(d) < DBL_EPSILON) {printf("double value: %g ,", fabs(d));std::cout << "is equal to zero!" << std::endl;} else {printf("double value: %g ,", fabs(d));std::cout << "is not equal to zero!" << std::endl;}return 0;
}

2.2 - 使用 limits 函数


我们可以使用 C++ 标准库中的 <limits> , 使用函数 epsilon 如下图

在这里插入图片描述

在具体程序中,我们可以定义两个常量,避免函数重复调用,引起性能损失。

#include <iostream>
#include <limits>
#include <cmath> // 一定要包含// 定义两个常量
constexpr double dbl_eps = std::numeric_limits<double>::epsilon();
constexpr float flt_eps = std::numeric_limits<float>::epsilon();int main(int argc, char* argv[])
{float f = 0.0;double d = 0.0;if (fabs(f) < flt_eps) {std::cout << "float value is equal to zero!" << std::endl;} else {std::cout << "float value is not equal to zero!" << std::endl;}if (fabs(d) < dbl_eps) {std::cout << "double value is equal to zero!" << std::endl;} else {std::cout << "double value is not equal to zero!" << std::endl;}return 0;
}

另外为了使用字符串与浮点数互相转换可以使用以下方法:

浮点数转字符串

#include <sstream>
#include <string>std::string DoubleToString(const double dvalue, int precision)
{std::stringstream ss;ss.precision(precision);ss.setf(std::ios::showpoint, std::ios_base::floatfield); // std::ios::showpoint 为了避免截断,如避免 1.000000000452 转为字符串为 1 的情况ss << dvalue;return ss.str();
}

字符串转浮点数

double StringToDouble(const std::string& str)
{try {return std::stod(str);}catch(...){std::cerr << "Unable to convert string:" << str << endl;return 0.0;}
}

3. 参考链接 References


  • CSDN
    https://blog.csdn.net/xp178171640/article/details/104565053

  • Stack Overflow
    https://stackoverflow.com/questions/9542391/float-double-equality-with-exact-zero

  • CppReference
    https://en.cppreference.com/w/cpp/types/numeric_limits

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_328907.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【七天入门数据库】第一天 MySQL的安装部署

系列文章传送门&#xff1a; 【七天入门数据库】第一天 MySQL的安装部署 【七天入门数据库】第二天 数据库理论基础 【七天入门数据库】第三天 MySQL的库表操作 MySQL数据库存在多种版本&#xff0c;不同的版本在不同的平台上&#xff08;OS&#xff0c;也就是操作系统上&a…

msvcr120.dll找不到是什么原因,怎样修复

msvcr120.dll的定义 msvcr120.dll是微软Visual C Redistributable软件包中的一个动态链接库文件。它是Microsoft Visual 所需的一个重要组件。这个文件主要用于支持和管理C语言编写的应用程序的运行。它包含了许多C的运行库函数和类&#xff0c;以便应用程序能够正常运行和调用…

Python(一):为什么我们要学习Python?

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

精确时钟同步协议ptp/IEEE-1588v2协议-------(2)主从时钟之间的消息交互与时钟同步过程

本文目录 1、主时钟和从时钟之间的消息交互流2、延时delay和偏移offset的计算2.1、延时delay的计算2.2、偏移offset的计算 主时钟和从时钟之间&#xff0c;通过sync, follow up, delay request, delay response这四条消息&#xff0c;完成时钟同步过程。PTP时钟同步系统能工作的…

3.8.cuda运行时API-使用cuda核函数加速yolov5后处理

目录 前言1. Yolov5后处理2. 后处理案例2.1 cpu_decode2.2 gpu_decode 总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习精简…

vue 2.0 的使用

day01 1. Vue简介 一套用于构建用户界面的 <font colorred>渐进式框架</font> 2. 初识Vue 2.1 搭建Vue开发环境 第一步&#xff1a;去<a href"https://v2.cn.vuejs.org/">Vue2官网</a>&#xff0c;下载依赖包。 第二步&#xff1a;在 …

多线程与并发编程【线程休眠、线程让步、线程联合、判断线程是否存活】(二)-全面详解(学习总结---从入门到深化)

目录 线程休眠 线程让步 线程联合 Thread类中的其他常用方法 判断线程是否存活 线程的优先级 线程休眠 sleep()方法&#xff1a;可以让正在运行的线程进入阻塞状态&#xff0c;直到休眠时间 满了&#xff0c;进入就绪状态。sleep方法的参数为休眠的毫秒数。 public class…

两部搞定Pytorch 安装与配置(小白也能搞定!!!)

Pytorch 安装与配置 NVIDIA系统管理界面查看 nvidia-smi 进入NVIDIA系统管理界面 对应的详细解释看下图 参考博文 (53条消息) nvidia-smi命令详解和一些高阶技巧介绍_Chaos_Wang_的博客-CSDN博客 CUDA 查看 CUDA 有两类&#xff1a;其中一类是驱动API(Driver API)&#xff…

实现windows系统文件传输到Linux系统中的工具

1、实现windows系统文件传输到Linux系统中的工具 yum -y install lrzsz然后就可以将windows中的文件&#xff0c;直接拖到Xshell窗口即可。

【钱处理】商业计算怎样才能保证精度不丢失

以项目驱动学习&#xff0c;以实践检验真知 前言 很多系统都有「处理金额」的需求&#xff0c;比如电商系统、财务系统、收银系统&#xff0c;等等。只要和钱扯上关系&#xff0c;就不得不打起十二万分精神来对待&#xff0c;一分一毫都不能出错&#xff0c;否则对系统和用户来…

Kafka入门,mysql5.7 Kafka-Eagle部署(二十五)

官网 https://www.kafka-eagle.org/ 下载解压 这里使用的是2.0.8 创建mysql数据库 创建名为ke数据库,新版本会自动创建&#xff0c;不会创建的话&#xff0c;自己手动创建&#xff0c;不然会报查不到相关表信息错误 SET NAMES utf8; SET FOREIGN_KEY_CHECKS 0;-- ------…

拥有铁粉,怀抱CSDN大家庭

&#x1f451; 个人主页 &#x1f451; &#xff1a;&#x1f61c;&#x1f61c;&#x1f61c;Fish_Vast&#x1f61c;&#x1f61c;&#x1f61c; &#x1f41d; 个人格言 &#x1f41d; &#xff1a;&#x1f9d0;&#x1f9d0;&#x1f9d0;说到做到&#xff0c;言出必行&am…

python_day4

def test():return 1, a, Truex, y, z test() print(f"x{x},y{y},z{z}")位置参数&#xff1a;调用时根据参数位置传递参数 关键字参数&#xff1a;调用时通过“键值”形式传参 def user(name, age, gender):print(f"name:{name},age:{age},gender:{gender}&q…

图床项目之公网发布和测试

项目发布和测试 一、http服务测试1.1、ab http压力测试1.2、post测试&#xff08;注册请求和登录请求&#xff09; 二、性能测试2.1、生成测试脚本2.2、上传测试2.2.1、单客户端测试本地上传到本机服务器2.2.2、如果使用集群的方式进行测试 2.3、下载测试2.4、删除测试2.5、测试…

springboot请求重定向失败问题解决方案

今天晚上在写登录页面时&#xff0c;发现自己的首页无法正常访问&#xff0c;用户名和密码正常的情况下还是无法访问首页。于是开始进行debug&#xff0c; 程序执行至此处时无任何异常&#xff0c;但是就是在进行重定向页面时出现了404&#xff0c;在检查导航栏后发现地址栏也发…

深度学习——批数据训练

代码与详细注释&#xff1a; BATCH_SIZE 5&#xff0c;shuffleTrue import torch import torch.utils.data as Data# 添加随机种子以使结果可复现 torch.manual_seed(1) # reproducible# 批大小 BATCH_SIZE 5 # BATCH_SIZE 8x torch.linspace(1, 10, 10) # this…

dvwa靶场通关(九)

第九关&#xff1a;Weak Session IDs&#xff08;弱会话IDs&#xff09; 当用户登录后&#xff0c;在服务器就会创建一个会话(session)&#xff0c;叫做会话控制&#xff0c;接着访问页面的时候就不用登录&#xff0c;只需要携带 Sesion去访问。 sessionID作为特定用户访问站…

用技术指标伦敦金行情走势图

经常有投资者说&#xff0c;伦敦金行情走势图老是涨跌涨跌&#xff0c;抓不准它涨跌的规律&#xff0c;老是被它弄得头昏脑胀。其实看伦敦金行情走势图的方法有很多&#xff0c;最直接的就是使用技术指标。技术指标本来就是投资者为了避免伦敦金行情走势图上价格干扰性波动&…

什么是热修复?它的优缺点是什么?

我们开发时常常要考虑的一些问题。 开发上线的版本能保证不存在Bug么&#xff1f; 修复后的版本能保证用户都及时更新么&#xff1f; 如何最大化减少线上Bug对业务的影响&#xff1f; 热修复技术帮助我们解决了很多问题&#xff0c;带来的优势不言而喻。不知道各位对于热修复技…

【AcWing算法基础课】第四章 数学知识(未完待续)

文章目录 前言课前温习番外&#xff1a;秦九韶算法核心模板 一、质数1. 试除法判定质数核心模板1.1题目描述1.2思路分析1.3代码实现 2、试除法分解质因数核心模板1.4题目描述1.5思路分析1.6代码实现 二、筛素数1.朴素筛法求素数核心模板2.线性筛法求素数&#xff08;O(n)&#…