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

这篇具有很好参考价值的文章主要介绍了【C++】float / double 与 0 值比较。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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-15

int 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 如下图

【C++】float / double 与 0 值比较,C++,c++,开发语言,经验分享,c语言

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

#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文章来源地址https://www.toymoban.com/news/detail-543570.html

到了这里,关于【C++】float / double 与 0 值比较的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言基本语句(变量类型int、 float、 double、 char,函数scanf、printf、putchar()、getchar() )

    1. int, float, double, char ①整型int(对应%d)  int a,b;  scanf(\\\"%d,%d\\\",a,b); printf (\\\"%d\\\",a); printf(\\\"我今天吃了%d个苹果,在黑板上写下整数%d,这很有趣。\\\",a,b); //printf(\\\"……\\\",变量名)中,“……”部分内容比较自由,可随便发挥,但必须包括%d,几个变量名就对应几个%d ②单精度型浮点数

    2024年02月08日
    浏览(52)
  • 涉及float和double

    它们会分成小数部分和指数部分分别存储。小数部分的有效位数越多,精度就越高,指数部分占位越多,能表示的数值范围越大。 一般float是4个字节,double是8个字节。 一般float的精度比double的大一些。 double的数值表示范围远远大于float。 该结论来源于谭浩强《C语言设计》的

    2024年02月07日
    浏览(30)
  • 【C语言深度解剖】float变量在内存中存储原理&&指针变量与“零值”比较

    大家好好我是沐曦希💕 根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式: (-1)^S * M * 2^E (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。 M表示有效数字,大于等于1,小于2。 2^E表示指数位。 例如: 十进制中的5.0转换成二进制

    2024年02月14日
    浏览(40)
  • float、double类型的转化和判断为零问题

    1、将字符串转化为float、double 浮点数在内存中的 存储机制和整形数据不同 ,有舍入误差,在计算机中用近似表示任意某个实数。具体来说,这个数由一个整数或定点数(即尾数)乘以某个基数(计算机中通常是2)的整数次幂得到。这种表示方法类似于基数为10的科学计数法

    2024年02月07日
    浏览(49)
  • 报错:RuntimeError: expected scalar type Double but found Float

    这个问题是深度学习,用pytorch跑的时候出现的 解决办法:这个是格式问题,希望的格式是double,但得到的是float。字面意思是这个,但是并不是非要把格式改成double,这个时候应该在出错的前面几处代码设个断点debug一下,我得到的结果是image、img_rgb都是tensor.unit8格式的,但

    2024年02月13日
    浏览(46)
  • loss.backward()处遇到“RuntimeError: Found dtype Double but expected Float”

    类型错误, 计算loss值的函数传入的参数类型不统一。 查看上文loss计算代码部分的参数类型,如loss=f.mse_loss(out,label),检查out和label的类型都是torch.float类型即可。使用label.dtype查看tensor的类型。 报错定位在这一行 寻思着是否是loss类型的问题,于是我就添加 但是还是报错在此

    2024年02月16日
    浏览(45)
  • 【已解决】Pytorch RuntimeError: expected scalar type Double but found Float

    本文作者: slience_me 在训练模型时候,将数据集输入到网络中去,在执行卷积nn.conv1d()的时候,报出此错误 报错堆栈信息 tensor的数据类型dtype不正确 这个错误通常是由于数据类型不匹配导致的。在PyTorch中,张量有不同的数据类型,如float32(FloatTensor)和float64(DoubleTensor)等

    2024年01月15日
    浏览(48)
  • Java开发手册中为什么禁止使用BigDecimal的equals方法做等值比较已经为什么禁止使用double直接构造BigDecimal

    阿里Java开发手册嵩山版中明确指出: 1、BigDecimal的等值比较应使用compareTo()方法,而不是equals()方法 equals()方法会比较值和精度(1.0与1.00返回结果为false),而compareTo()则会忽略精度 2、禁止使用构造方法BigDecimal(double)的方式把double值转换为BigDecimal对象 BigDecimal(double)存在精度损

    2024年02月07日
    浏览(56)
  • 主流架构(gcc、msvc、x86、x64、arm)中double与float浮点数保留精度(末尾清零)

    ​​​​​​ float  是 单精度浮点数 ,内存占4个字节,有效数字8位,表示范围是 -3.40E+38~3.40E+38。 double  是 双精度浮点数 ,内存占8个字节,有效数字16位,表示范是-1.79E+308~-1.79E+308。     C和C++标准没有指定EDCOX1、1、EDCOX1、0和EDCOX1×9的表示。这三个都有可能实现为IEEE双精

    2024年02月08日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包