草庐IT

【C语言】浮点数和0比较

yuelinghou 2023-04-27 原文

文章目录

一. 浮点数存储时是有精度损失的

下面程序中我们打印一个浮点数的值

int main()
{
	double d = 3.6;
	printf("%.50f\n", d);
	return 0;
}

观察到浮点数存储在内存空间中是有内存损失的:

二. 浮点数不能直接进行 == 比较

所有存储在内存中的浮点数都不能做到完全精确,如果拿它们进行计算,那误差更是在所难免。

int main()
{
	double x = 1.0;
	double y = 0.1;
	printf("%.50f\n", x - 0.9);// 预计得到0.1
	printf("%.50f\n", y);

	if ((x - 0.9) == y)
	{
		printf("you can see me!\n");
	}
	else
	{
		printf("oops!\n");
	}
	return 0;
}

编译运行:

三. 使用精度来比较两个浮点数是否相等

既然浮点数的误差在所难免,那么我们可以考虑两个浮点数相等的条件是:它们差值的绝对值是一个很小的数的话,那么可以说这两个浮点数是相等的。

我们可以自定义一个最小差值,或者叫最小精确度EPSILON,它的值是 0.0000001

#define EPSILON 0.0000001

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) > -EPSILON && ((x - 0.9) - y) < EPSILON)
	if (fabs((x - 0.9) - y) < EPSILON)
	{
		printf("you can see me!\n");
	}
	else
	{
		printf("oops!\n");
	}
	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

四. 浮点数和0比较

上面我们知道了判断两个浮点数是否相等的方法就是看

if ( fabs(x - y) < DBL_EPSILON)

这个条件是否成立。

是否可以以此类推,判断一个浮点数 x 是否和 0 相等的话就是看

if ( fabs(x - 0) < DBL_EPSILON) 即 if ( fabs(x) < DBL_EPSILON)

下面用一段代码举例:

int main()
{
	double x = 0.000000000000000000000001;
	if (fabs(x) < DBL_EPSILON)
	{
		printf("x == 0.0\n");
	}
	else
	{
		printf("x != 0.0\n");
	}
	return 0;
}

编译运行:

还有一个问题,就是用绝对值和 DBL_EPSILON 进行比较时能否用 <= 呢?

我们在来看看 DBL_EPSILON 是怎么定义的:


所有两个浮点数如果要相等,那它们差值的绝对值肯定是要小于DBL_EPSILON的,相等都不行。

有关【C语言】浮点数和0比较的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  3. ruby - 寻找通过阅读代码确定编程语言的ruby gem? - 2

    几个月前,我读了一篇关于ruby​​gem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:

  4. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  5. 7个大一C语言必学的程序 / C语言经典代码大全 - 2

    嗨~大家好,这里是可莉!今天给大家带来的是7个C语言的经典基础代码~那一起往下看下去把【程序一】打印100到200之间的素数#includeintmain(){ inti; for(i=100;i 【程序二】输出乘法口诀表#includeintmain(){inti;for(i=1;i 【程序三】判断1000年---2000年之间的闰年#includeintmain(){intyear;for(year=1000;year 【程序四】给定两个整形变量的值,将两个值的内容进行交换。这里提供两种方法来进行交换,第一种为创建临时变量来进行交换,第二种是不创建临时变量而直接进行交换。1.创建临时变量来

  6. ruby-on-rails - ruby on rails 模型验证中的浮点精度 - 2

    我正在尝试使用正则表达式验证美元金额:^[0-9]+\.[0-9]{2}$这工作正常,但每当用户提交表单并且美元金额以0(零)结尾时,ruby(或rails?)将0砍掉。所以500.00变成500.0,因此正则表达式验证失败。有没有办法让ruby​​/rails保持用户输入的格式,而不管尾随零? 最佳答案 我假设您的美元金额是小数类型。因此,用户在字段中输入的任何值在保存到数据库之前都会从字符串转换为适当的类型。验证适用于已转换为数字类型的值,因此在您的情况下,正则表达式并不是真正合适的验证过滤器。不过,您有几种可能性可以解决这个问

  7. ruby - 是否有用于复杂比较的漂亮语法? - 2

    方法应返回-1,0或1分别表示“小于”、“等于”和“大于”。对于某些类型的可排序对象,通常将排序顺序基于多个属性。以下是可行的,但我认为它看起来很笨拙:classLeagueStatsattr_accessor:points,:goal_diffdefinitializepts,gd@points=pts@goal_diff=gdenddefothercompare_pts=pointsother.pointsreturncompare_ptsunlesscompare_pts==0goal_diffother.goal_diffendend尝试一下:[LeagueStats.new(

  8. ruby-on-rails - 浮点乘法的 Ruby 奇怪问题 - 2

    有没有人用ruby​​解决这个问题:假设我们有:a=8.1999999我们想将它四舍五入为2位小数,即8.20,然后乘以1,000,000得到8,200,000我们是这样做的;(a.round(2)*1000000).to_i但是我们得到的是8199999,为什么?奇怪的是,如果我们乘以1000、100000或10000000而不是1000000,我们会得到正确的结果。有人知道为什么吗?我们正在使用ruby​​1.9.2并尝试使用1.9.3。谢谢! 最佳答案 每当你在计算中得到时髦的数字时使用bigdecimalrequire'bi

  9. ruby - 尝试比较两个文本文件,并根据信息创建第三个 - 2

    我有两个文本文件,master.txt和926.txt。如果926.txt中有一行不在master.txt中,我想写入一个新文件notinbook.txt。我写了我能想到的最好的东西,但考虑到我是一个糟糕的/新手程序员,它失败了。这是我的东西g=File.new("notinbook.txt","w")File.open("926.txt","r")do|f|while(line=f.gets)x=line.chompifFile.open("master.txt","w")do|h|endwhile(line=h.gets)ifline.chomp!=xputslineendende

  10. ruby-on-rails - 我如何比较 'Bcrypt' Gem解密的密码和加密的密码 - 2

    我正在尝试对某些帖子的评论使用简单的身份验证。用户使用即时ID和密码输入评论我使用“bcrypt”gem将密码存储在数据库中。在comments_controller.rb中像这样@comment=Comment.new(comment_params)bcrypted_pwd=BCrypt::Password.create(@comment.user_pwd)@comment.user_pwd=bcrypted_pwd当用户想要删除他们的评论时,我使用data-confirm-modalgem来确认数据在这部分,我必须解密用户输入的密码以与数据库中的加密密码进行比较我怎样才能解密密码,

随机推荐