比较C中的相同浮点值

时间:2012-03-24 09:41:05

标签: c++ c floating-point floating-accuracy

  

可能重复:
  strange output in comparison of float with float literal

当我尝试比较两个相同的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();
}

提前致谢。

7 个答案:

答案 0 :(得分:25)

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

您的具体问题在于:

float a = 0.7;

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

if (a == 0.7)

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

0.7转换为双倍a时,将a转换为浮动0.7时丢失的精度不会重新获得。

如果你将所有0.7f值更改为a(强制浮动而不是加倍),或者只是让float加倍,它会正常工作 - 我很少使用#include <stdio.h> 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.

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

{{1}}

答案 1 :(得分:4)

浮点数不是您认为的那样:以下是两个包含更多信息的来源:What Every Computer Scientist Should Know About Floating-Point ArithmeticThe Floating-Point Guide

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

答案 2 :(得分:3)

您正在将单精度近似值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

答案 3 :(得分:2)

afloat; 0.7double类型的值。

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

但是请不要将浮点值(floatdoublelong double)与==进行比较。

您可能希望阅读"What Every Programmer Should Know About Floating-Point Arithmetic"

答案 4 :(得分:0)

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

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)

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

Another article几乎是与人们在SO上询问浮动时相关的事实上的标准。

答案 5 :(得分:0)

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

不是将浮点数与“==”运算符进行比较,而是可以使用如下函数:

 //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;
   }
 }

答案 6 :(得分:-1)

如果您需要将a0.7进行比较

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

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