Sam Brinck
Sam Brinck

Reputation: 901

c++ compare function result

I have the following code that is exhibiting some very strange behavior. does anyone have any idea why.

#include <iostream>

long global = 20001;

double foo() {return global / 1000.0;}

int main(int,char**) {
  if (foo() == foo()) {
    std::cout << "true\n";
  } else {
    std::cout << "false\n";
  }

  return 0;
}

This should print true as the function returns the same result each time but instead prints false;

This is built using g++ on Solaris 10. I don't know that the OS matter, but I haven't had a chance to try it on a different os

Upvotes: 2

Views: 97

Answers (2)

James Kanze
James Kanze

Reputation: 153919

The OS probably doesn't matter, but the compiler and the architecture do. On an Intel, the usual convention is to return a floating point value in a floating point register, which has 64 bits precision (rather than the 53 of a double). And of course, the compiler does the arithmetic directly into that register, so you end up returning a value with 64 bits precision.

Of course, when the compiler generates code to call a function, it can't leave the value in a register, since the function might use that register. So it spills it to memory. As a double with 56 bits. The == operator compares this 56 bit value from the first call with the 64 bit value from the second, and finds that they aren't equal.

I might add that if the compiler inlines the functions, the problem will probably disappear.

All of which is perfectly legal according to the standard.

Upvotes: 3

Jmc
Jmc

Reputation: 830

Likely a problem with doubles not evaluating to exactly the same value all the time (essentially rounding errors).

If you were to change your function to return integers, you would probably have the expected behaviour.

Very similar to this question: Deals with comparing floats

Try this:

#include <iostream>
#include <limits>

long   global = 20001;
double epsilon = std::numeric_limits::epsilon<double>();

double foo() {return global / 1000.0;}

int main(int,char**) {
  if (foo() - foo() > epsilon) {
    std::cout << "true\n";
  } else {
    std::cout << "false\n";
  }

  return 0;
}

Upvotes: 1

Related Questions