比较C中的相同浮点值

可能重复:
与float和float文字相比较的奇怪输出

当我尝试比较2个相同的float值时,它不会在以下代码中打印“相等的值”:

 void main() { float a = 0.7; clrscr(); if (a < 0.7) printf("value : %f",a); else if (a == 0.7) printf("equal values"); else printf("hello"); getch(); } 

提前致谢。

虽然很多人会告诉你总是将浮点数与epsilon进行比较(这通常是一个好主意,虽然它应该是被比较的值的百分比而不是固定值),但这里实际上并不是必需的,因为你是使用常量。

你的具体问题是:

 float a = 0.7; 

使用常数0.7来创建单个精度数(失去一些精度),同时:

 if (a == 0.7) 

将比较两个精度数字( a首先提升)。

将双0.7转入浮球a时丢失的精度在将背部提升为双倍时无法恢复。

如果你将所有这0.7值更改为0.7f (强制浮动而不是双倍),或者如果你只做一个双float ,它将正常工作 – 我现在很少使用float除非我有大量数组并需要保存空间。

您可以通过以下方式查看此操作:

 #include  int main (void){ float f = 0.7; // double converted to float double d1 = 0.7; // double kept as double double d2 = f; // float converted back to double printf ("double: %.30f\n", d1); printf ("double from float: %.30f\n", d2); return 0; } 

这将输出类似的东西(略微修改以显示差异):

 double: 0.6999999|99999999955591079014994 double from float: 0.6999999|88079071044921875000000 \_ different beyond here. 

浮点数不是你想象的那样:这里有两个有更多信息的来源: 每个计算机科学家应该知道浮点运算和浮点指南 。

简短的回答是,由于表示浮点数的方式,您无法进行基本比较或算术并期望它能够工作。

您正在将0.7的单精度近似与双精度近似进行比较。 要获得预期的输出,您应该使用:

 if(a == 0.7f) // check a is exactly 0.7f 

请注意,由于表示和舍入错误,可能不太可能从任何操作获得正好0.7f。 通常,您应该检查fabs(a-0.7)是否足够接近0

不要忘记0.7f的确切值不是0.7,而是略低:

 0.7f = 0.699999988079071044921875 

0.7的双精度表示的精确值是更好的近似值,但仍不完全是0.7:

 0.7d = 0.6999999999999999555910790149937383830547332763671875 

afloat ; 0.7double类型的值。

两者之间的比较需要转换。 编译器会将float值转换为double值…而将float转换为double所产生的值与编译器将文本字符串(源代码)转换为double所产生的值不同。

但是不要将浮点值( floatdoublelong double )与==

您可能希望阅读“每个程序员应该知道的关于浮点运算的内容” 。

不能将浮点数与“==”运算符进行比较。

您可以使用如下函数来代替将浮点数与“==”运算符进行比较:

  //compares if the float f1 is equal with f2 and returns 1 if true and 0 if false int compare_float(float f1, float f2) { float precision = 0.00001; if (((f1 - precision) < f2) && ((f1 + precision) > f2)) { return 1; } else { return 0; } } 

浮点数缺乏绝对精度使得进行简单比较比整数更难。 请参阅此页面以比较C中的浮点数。特别是,从那里取出的一个代码段展示了此问题的“解决方法”:

 bool AlmostEqual2sComplement(float A, float B, int maxUlps) { // Make sure maxUlps is non-negative and small enough that the // default NAN won't compare as equal to anything. assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); int aInt = *(int*)&A; // Make aInt lexicographically ordered as a twos-complement int if (aInt < 0) aInt = 0x80000000 - aInt; // Make bInt lexicographically ordered as a twos-complement int int bInt = *(int*)&B; if (bInt < 0) bInt = 0x80000000 - bInt; int intDiff = abs(aInt - bInt); if (intDiff <= maxUlps) return true; return false; } 

一个简单而常见的解决方法是为epsilon提供如下代码:

 if (fabs(result - expectedResult) < 0.00001) 

这基本上检查了值之间的差异是否在阈值内。 请参阅链接文章,了解为什么这并不总是最佳的:)

另一篇文章几乎是事实上的标准,当人们询问SO上的浮动时。

如果你需要比较a 0.7

 if( fabs(a-0.7) < 0.00001 ) //your code 

这里0.00001可以更改为更少(如0.00000001)或更多(如0.0001)>这取决于您需要的精度。