有没有办法正确比较1浮点值是大于还是小于另一个?

时间:2015-09-23 07:41:44

标签: c++ floating-point

我一直在阅读布鲁斯道森关于如何比较浮点值的this article。但他的所有例子都在检查是否

void copy(char *srcFilename, char *dstFileName)
{
  FILE *fsrc, *fdst;
  char c;

  printf("Inside copy function\n");
  fsrc=fopen(srcFilename, "rb");

  if (fsrc==NULL) 
  {
    printf("Couldn't open file %s for reading.\n", srcFilename);
    exit(0);
  }

  /* Add usual error check */
  fdst=fopen (dstFileName, "w");
  /*Add usual error check */
  for ( ; !feof(fsrc); )
  fputc (fgetc (fsrc), fdst);

  fclose (fsrc);
  fclose (fdst);
}

所以我想知道是否有适当的比较方法

  floatA == floatB. 

  floatA > floatB 

或者是< ,>运算符是否足以考虑浮点值?

编辑:我对如何检查平等没有兴趣。如果有一种方法可以检查一个浮点值是否小于/大于另一个,我感兴趣。

3 个答案:

答案 0 :(得分:3)

比较浮点数是否相等的问题是许多数字在二进制浮点数中没有精确的表示。例如,0.1不能用浮点精确表示,只是非常接近的近似值。

因此,当你采用该近似值并将其乘以10时,你得不到你想象中的1.0。

因此,如果你写“if(0.1 * 10 == 1.0)”,你将无法得到你期望的结果,你很可能会得到假的。

同样的问题适用于小于和大于。

“if(0.1 * 10< 1.0)” - 这不应该是真的,因为值是相等的。 然而在实践中它可能是正确的,因为0.1是一个非常小于0.1的近似值,并且将它乘以10会得到一个非常小于1.0的值,当测试结果为假时,测试结果为真。

如果您的比较可能会受到影响,那么您需要适当地处理它。

在可能的情况下,这不是问题。 if(distance_to_work< 10.0)//可能不会导致问题 但有些可能是

答案 1 :(得分:0)

无论您如何比较浮点数的相等性,请确保其他比较运算符与equal运算符的行为一致。

如果是<,您需要保证!(a < b) && !(b < a)a == b相同。

我们说,您实现了以下equal函数:

const double EPSILON = 10e-8;

bool equal(double a, double b)
{
   return fabs(a - b) < EPSILON;
}

使用<运算符并不总是安全的,因为它可能会得到不一致的结果。

double a = 0.1 + 0.2;
double b = 0.3;

equal(a, b);  // true
a < b;        // false
b < a;        // TRUE

请参阅b < aequal(a, b)返回true,这在语义上是不正确的。

最简单的方法是使用equal函数定义less

bool less(double a, double b)
{
   return a < b && !equal(a, b);
}

现在,它是一致的

double a = 0.1 + 0.2;
double b = 0.3;

equal(a, b);  // true
less(a, b);   // false
less(b, a);   // false

使用相同的方法来定义其他操作(例如greaterlessOrEq等)。这种一致性可以让你在实践中避免一堆微妙的错误。

答案 2 :(得分:-2)

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