C语言中double与float的比较

22 篇文章 20 订阅
订阅专栏

目录

目录

1.问题发现

2.原因分析

3.问题"解决"

4.何为精度损失

4.浮点数的正确比较方法

        1.问题再现

        2.最终解决方案


1.问题发现

   在编程中我们时常要判断两个数是否相等,我们先来看一段简单的代码,猜猜运行结果是什么:

#include<stdio.h>
int main()
{
	float t=3.197;
	if (t == 3.197)
	{
		printf("hehe");
	}
	else
		printf("haha");
	return 0;
}

你是否也和我一样认为t恒等于3.197,先别急,让编译器来告诉我们答案:

3c7f680042194d68af33e4de26505caa.png

2.原因分析

为什么会打印“haha呢”,难道编译器出错了?实则不然。

其实,当我们写下小数时,编译器会自动把它当做double类型:

701d9b8189d7467c8884077d9df2f659.png

而由于我们的t是float类型,占4个字节,而double类型占8个字节,由于浮点数在内存中以IEEE754标准进行存放,就会出现精度损失(下面讲解)的问题。当float与double类型进行比较时,不同类型存放数据的精度不同,编译器就会认为不相同,打印输出“haha”。

3.问题"解决"

那么,该如何解决这个问题使最后程序运行的结果为我们想要的答案?你可能会想到以下几种方法:

1.将变量t定义为double类型

double t=3.197;

2.在小数后加f使其变为float类型

float t=3.197f;

3.使用()运算符将3.197强制类型转化为double类型

float t =(float)3.197;

通过以上改进,程序成功输出“hehe”:

2770dbba1efa46b1a5bfe3bde9912eea.png

4.何为精度损失

无论单精度浮点数还是双精度浮点数,在计算机中都是以IEEE754的方式来进行存放。

我们知道float占32个比特位,其在计算机内存中存放的格式如下:

8939f8e7d28c48f18219583dce35da7f.png

而double占64个比特位,其在计算机内存中存放的格式如下:

24b5443a89fe463d9b557ee44906f51b.png

其中符号位1表示负,0表示正,阶码部分用指数部分的移码表示,而尾数部分正是决定精度的重要部分,对于不同的类型,其能表示的精度不同,从上图可看出double类型表示比用float类型表示精度更高。

当小数转化为二进制时,往往会出现无限位数的情况,而数据显然不能无限存储,这时计算机就要进行截取,而截取的位数就取决于尾数的位数

正因如此,计算机常常出现精度丢失的问题。这就是为什么上述问题会引起歧义的原因。

此外,当double隐式转化为float类型时,由于位数不同,计算机也会实行截断,造成精度丢失。值得注意的是,一个浮点数的的整数部分存储在尾数位置的高位,因此发生截断时整数部分经常可能会出现错误,而小数部分相较于整数部分影响甚微,在一些场合下可以忽略不计

4.浮点数的正确比较方法

        1.问题再现

        虽然通过我们的修改程序成功输出了hehe,但是我们的问题真的解决了吗?上例我们只是将两个以字面值出现的浮点数进行比较,但如果出现的是一个表达式呢?我们来看以下代码:
 

#include<stdio.h>
int main()
{
	double t1 = 1.0;
	double t2=  0.1;
	if (t2 == t1-0.9)
	{
		printf("hehe");
	}
	else
		printf("haha");
	return 0;
}

        按照我们之前的分析,等号两边的类型和值一样,因此会打印hehe。但是结果不以为然,运行程序,程序打印haha:

         为什么会出现错误呢?其实原因依旧逃不开精度(万恶之源)。我们通过上面分析知道浮点数存储时会出现精度丢失的问题,例如t2实际存储的并非严格的0.1,而是一个极为接近0.1的数。并且,在t1-0.9这个表达式中,0.9也是存在精度损失的,最终计算的结果也并非是0.1。因此,最后二者不等,输出haha。我们也可以通过编写程序来验证:

#include<stdio.h>
int main()
{
	double t1 = 1.0;
	double t2=  0.1;
	printf("%.50lf\n", t1 );
	printf("%.50lf\n", t2);
	printf("%.50lf\n", t1 - 0.9);
	return 0;
}

我们可以直观的看到,由于t1小数部分为0,因此不存在精度损失的问题。但是t2和t1-0.9就不一样了由于精度损失的问题,t2存储的内容并非为0.1,t1-0.9的结果也并非为0.1。我们可以看出,二者尽管非常接近0.1,但还是略有不同,依旧逃离不了编译器的法眼。

         2.最终解决方案

        "天啊,这也太折磨人了吧",看到这里,会不会有人发出感叹呢(好奇^v^)。由上分析,我们得出的结论是我们不能单纯用==来进行浮点运算的比较。我们发现t2和t1-0.9的差距十分的小,因此我们可以设定一个非常小的阈值,通过判断二者差的绝对值是否小于阈值来判断二者是否相等。其中,对于阈值,在float.h头文件中有定义,当然我们也可以自己设定阈值

#include<stdio.h>
#include<float.h>
#include<math.h>
int main()
{
	double t1 = 1.0;
	double t2=  0.1;
	//错误的,不能直接比较
	//if((t1-0.9)==t2)
	//{
	//	printf("hehe");
	//}

	//正确做法,通过阈值比较,DBL_EPSILON为浮点数阈值,使得1.0加上后不等于1.0的最小值
	if (fabs((t1 - 0.9) - t2) < DBL_EPSILON)   
	{
		printf("hehe");
	}
	else
	{
		printf("haha");
	}
	return 0;
}

对于float.h定义的阈值,其定义是使得1.0加上后的值不等于1.0的最小值。换句话说就是两个数差值如果小于这个最小值,两个数就相等。我们可以由此进行浮点数的比较。


以上,就是本期的所有内容了

制作不易,能否点个赞再走呢!

C语言--浮点数的比较
简单 & 执着
06-11 5804
先说结论:浮点数不能直接用"=="进行比较 观察代码 看如下代码,分析输出: void testDoubleCompare() { float a = (float)0.1; float b = (float)0.1; float c = (float)0.1; double d = (double)0.1; //同样精度,同样字面大小 if(a == b) printf("a==b\n"); else printf("a!=b\n"); //不同精度,同样字面大小
初始C语言float double 区别
Chinadrakk的博客
07-13 1647
一般来说,CPU处理单精度浮点数的速度比处理双精度浮点数快,如果不声明,默认小数为double,因此,如果要用float的话,必须进行强转。double的表达式为1bit(符号位)+ 11bits(指数位)+ 52bits(尾数位)double占8个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308。float的表达式为1bit(符号位)+8bits(指数位)+23bits(尾数位)float占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38。
C语言浮点数的比较
Mr.Simple的专栏
06-19 2351
使用设定的精度来判断,还不是直接对比 , 如下:float local, first, result ; const float EPSINON = 0.0000001; local = 10.3456783; first = 10.3456894; result = 0.0; result = local - fisrt; if(result > EPSINON) // 两浮点数之差大于
C 语言两个浮点数比较
weixin_43743711的博客
08-08 1254
//浮点数并非真正意义上的实数,只是其在某个范围内的近似。 //因此两个浮点数比较大小时,不能简单地使用大于小于号进行比较,应该判断连个浮点数差值的绝对值是否近似为0。 #include <stdio.h> #include<math.h> #define EPS 1e-7 //判断浮点数是否位于0的一个很小的邻域内[-EPS,EPS]内 main(){ /*判断一个浮点数是否等于0*/ float a; scanf
C语言(关于浮点数比较的学习)
weixin_64113211的博客
05-29 790
由于浮点数十进制转化成二进制的机制,会造成精度损失,因此在浮点数的比较,无法直接令两个浮点数是否相等来判断两个浮点数,如: #include<stdio.h> int main() { double x = 1.0; double y = 0.1; if(x - 0.9 == y) printf("Yes"); else printf("No"); } //结果为"No" 在比较两个浮点数是否相等时,引入高数无穷小的概念,当两个浮点数相减比一个很小的数还要小时,可认为两个浮点
C语言浮点类比较
wangjianhs的博客
04-18 3175
C语言浮点类比较 我们都知道C数据在计算机里是以二进制数存储的,但是关于浮点数呢比如float a=125.125计算机将其转化为1111101.001B的二进制数,可是问题在于计算机根本不认识小数点。 历史上计算机科学家们曾提出过多种解决方案,最终获得广泛应用的是IEEE 754标准的方案,目前最新版的标准是IEEE std 754-2008。该标准提出数字系统的浮点数是对数学...
C语言float double数据转换成HEX
08-04
C语言,将`float`和`double`类的数值转换为HEX(十六进制)格式是一项常见的任务,尤其在处理二进制数据、内存表示或者进行低级编程时。下面将详细介绍如何进行这样的转换,并对提供的代码片段进行解析。 ...
C语言doublefloat 实例分析
09-01
C语言,浮点数是用来表示实数的,它们分为两种主要的数据类:`float`和`double`。这两个类都是用来存储带有小数部分的数值,但它们在存储精度和内存占用上有显著的区别。 1. **浮点数的概念**: 浮点数在...
c语言double是几字节,c语言int long float double 等类所占字节及输出表示(转)...
weixin_39883440的博客
05-17 2078
16位编译器char :1个字节char*(即指针变量): 2个字节short int : 2个字节int: 2个字节unsigned int : 2个字节float: 4个字节double: 8个字节long: 4个字节long long: 8个字节unsigned long: 4个字节32位编译器(看这里就行了,与16位机,64位机比较,粗体type为不同的,其余的都是相同)char :1个字...
C语言浮点值的比较
m0_66599463的博客
07-02 699
C语言浮点值的比较
float数和double的大小比较
11-19 6316
看到一个面试题想了很久为什么? float f = 1.4f;double d = 1.4d; 与 float f = 1.5f;double d = 1.5d; 是否为true float f = 1.4f; double d = 1.4d; float f1 = 1.5f; double d1 = 1.5d; while (true) { System.out.println(f...
C++的浮点数double的精度问题以及大小比较
Mikchy的博客
08-04 7892
由于double浮点数的精度问题,所以在比较大小的时候,不能像int整数那样,直接if(a==b),if(a&lt;b),if(a&gt;b) 要使用一个精度EPS: const double EPS = 1e-6; //一般这样子就够,但有时具体题目要考虑是否要更小的 if(fabs(a-b) &lt; EPS) //判断是否相等 if(a &gt; b+EPS) // 判断...
C/C++ 比较double的变量
qq_38656988的博客
10-18 3036
double比较, 浮点数的表示方法
浮点数比大小(C语言版)
m0_62101546的博客
01-10 1万+
1.浮点数可以直接用大于号小于号等于直接比大小吗? 可以是可以,但是只能在最大的精度范围内,否则会有错误。所以最好不要直接比。 2.如何进行浮点数的比较? 宏定义一个变量为EPS(变量名自己取),EPS是一个很小的数,接近于0 使EPS的值为1e-7(表示0.0000001,指数计数,e前的1和e后的-不可省略) 利用求绝对值的fabs()函数(记得写头文件math.h)eg:fas(-1.2)=1.2 举个例子 输入两个浮点数判断两个数是否相等 #include <stdio.h&g
float,double范围和精度
plussai的博客
06-23 252
         今天遇到一题zoj_1128,数据范围是(0&lt;=x1&lt;x2&lt;=100000;0&lt;=y1&lt;y2&lt;=100000),所有的数不一定是整数,并且最后输出的结果保留2位小数。用float死活wa,最后double过了,痛过之后来总结一下floatdouble的范围精度。 下面引用:http://www.cnblogs.com/BradMiller/...
C语言double比较大小
csdn_gddf102384398的博客
05-17 1040
C语言double比较大小。
C语言floatdouble区别及用法
热门推荐
顾得泉的博客
04-06 2万+
使用场景:一般情况下,如果需要高精度计算,应该使用double;需要注意的是,在进行浮点数运算时,由于浮点数存在精度问题,可能会出现一些意料之外的结果,因此需要谨慎使用。运算速度:如果需要快速进行浮点数运算,可以使用float,因为它占用的存储空间更小,运算速度更快。精度要求:如果需要高精度计算,应该使用double,因为它能够表示更小精度的数值。存储空间:如果需要节省存储空间,可以使用float,因为它占用的存储空间更小。精度:doublefloat精度更高,能够表示更大范围和更小精度的数值。
c语言 double比较大小吗,C语言两个DOUBLE变量的比较问题
weixin_42530570的博客
05-17 1671
匿名用户1级2006-07-24 回答由于计算机字长有限,无法精确表示数字,因此对有些数只能是一个近似double的字长是8个字节,而2.001转换成2进制是11.00000...是个无限小数此类浮点数在计算机内采用 阶码+尾数 方式存储ieee 64的存储方式如下阶符 阶码 尾数double 1 11 52阶码部分由于有11位因此可以表示2^11次方范围的数 在本题所涉及的...
C语言的浮点数比较
bdss58的专栏
11-30 3581
浮点数分为单精度和双精度两种。在内存的存储方式按照IEEE754标准。通常情况下,单精度占4个字节,双精度占8个字节。可以使用sizeof验证一下。 #include int main() { float x=0.1;//单精度 double y=0.1;//双精度 printf("%d %d\n",sizeof(x),sizeof(y)); } 输出结果为4 8;
c语言doublefloat的用法
最新发布
11-15
C语言doublefloat都是用来表示浮点数的数据类float通常使用4个字节来存储,而double则使用8个字节来存储,因此double的精度更高。 在C语言,我们可以使用float来定义单精度浮点数,即小数点后面的数字...
60
原创
3139
点赞
3449
收藏
7253
粉丝
关注
私信
写文章

热门文章

  • C语言学习之取整取余 21752
  • C语言学习之void关键字 15901
  • C语言学习之extern关键字 13168
  • C语言学习之sizeof与strlen 6699
  • C语言之函数栈帧(动图详解) 4776

分类专栏

  • C语言学习打卡 22篇
  • C++深入浅出 10篇
  • 数据结构 10篇
  • 剑指offer 4篇
  • C语言刷题打卡 10篇
  • 小项目总集 3篇

最新评论

  • C语言学习之取整取余

    病酒红尘: 正无穷取整是ceil吧,红字部分打错了

  • C语言之函数栈帧(动图详解)

    Lalo666666: 优质文章表情包,很用心。

  • 【C++深入浅出】STL之string用法详解

    小王毕业啦: 博主的这篇文章对STL中string的用法进行了详细解析,让我对这个话题有了更深入的了解。文章中的细节描写非常到位,让我感受到了博主的专业知识和深厚功底。期待博主未来能够持续分享更多类似的好文,同时也希望能够得到博主的指导,一起共同进步。非常感谢博主的用心分享和支持!

  • C语言之函数栈帧(动图详解)

    忆梦初心: call指令执行的过程是先将返回地址压入栈中,然后再跳转。

  • C语言之函数栈帧(动图详解)

    pjk219572421: 这一段没看明白。你的图里面没看到哪一行汇编指令是将00EE18F7压到栈里面: 点击F11进入函数,我们可以发现函数返回后的指令地址被压入栈中(即00EE18F7),然后修改eip进行跳转,转入Add()函数:

最新文章

  • 【C++深入浅出】STL之string用法详解
  • 【C++深入浅出】模版初识
  • 【C++深入浅出】C/C++内存管理(教你如何new到对象)
2023年45篇
2022年15篇

目录

目录

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

忆梦初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家玻璃钢雕塑喷漆多少钱一平方武威彩色玻璃钢雕塑定做邓州玻璃钢雕塑定制豪晋玻璃钢雕塑梁子湖玻璃钢花盆花器惠州玻璃钢雕塑生产厂家潮州户外玻璃钢雕塑湖北欧式玻璃钢雕塑价位什么公司装修会用到玻璃钢雕塑湖北玻璃钢香蕉雕塑商场秋季护肤美陈饮料商场创意美陈室内玻璃钢雕塑制作多少钱嘉峪关动物玻璃钢雕塑公司丹灶玻璃钢人物雕塑免费咨询芒市玻璃钢人物雕塑玻璃钢雕塑上青铜色江苏知名玻璃钢雕塑厂家直供徐州玻璃钢商场美陈云浮玻璃钢蘑菇雕塑制作厂新密玻璃钢雕塑加工西安商场春季美陈文具店卡通玻璃钢雕塑艺术玻璃钢雕塑厂家工厂太原玻璃钢雕塑制作广州欧式玻璃钢人物雕塑信阳知名玻璃钢卡通雕塑中山玻璃钢雕塑品龙岩玻璃钢雕塑制作彭州玻璃钢长颈雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化