4

How to reproduce this behavior? https://isocpp.org/wiki/faq/newbie#floating-point-arith2

To be precise, in the following code, parameters x and y are equal; they can be equal to 1.0 or any other value.

void foo(double x, double y)
{
  double cos_x = cos(x);
  double cos_y = cos(y);
  // the behavior might depend on what's in here
  if (cos_x != cos_y) {
    std::cout << "Huh?!?\n";  // You might end up here when x == y!!
  }
}

Some compiler options? Loop? Any idea?

anatolyg
  • 26,506
  • 9
  • 60
  • 134
userbb
  • 2,148
  • 5
  • 30
  • 53
  • You can't. It all depends on your configuration as to what happens. that's why there is the comment `// You might end up here when x == y!!` – NathanOliver Jun 11 '15 at 16:32
  • Try a high-precision (read: _very long_) number that you can type out with many decimal places and see what happens. – Ricky Mutschlechner Jun 11 '15 at 16:50
  • 1
    You'll need an old version of your C compiler, one that still generates FPU code with the dreaded 80-bit internal format, and enough energy to tinker with the code so the optimizer breaks it. That's a week of your life you'll never get back. The point is that this could happen without you having to look for it. – Hans Passant Jun 11 '15 at 16:56
  • I don't think this is as likely to happen as the article makes it seem. It is _possible_ for it to happen, but it's not that likely – Daniel Jun 11 '15 at 16:59
  • @HansPassant so with new compilers this would not theoretically happen? even with some compiler options? – userbb Jun 11 '15 at 16:59
  • `cos(x) != cos_y` yelds the same result?. Also compile with optimizations off (-O0 in gcc) – Vinicius Kamakura Jun 11 '15 at 17:00
  • @userbb On MS Visual Studio, use `/arch:IA32` to force code generation for the old FPU with the 80-bit format. Only then it will theoretically be able to happen, but you will have to tinker a lot to reproduce it (or write sufficiently important code to invoke Murphy's Law). – anatolyg Jun 11 '15 at 17:01
  • @HansPassant: You should make that an answer, since (a) you are correct and (b) you are the only one so far who is – Nemo Jun 11 '15 at 17:12

1 Answers1

3

I would try doing it the way it is done in the linked example: without storing the results to temporary variables. The article mentions that floating point arithmetic is often calculated in registers that have more bits than the RAM. If there is, for example, only one floating point arithmetic register, then after doing the cos calculation, the result has to be stored in RAM in order to do the other cos calculation. From the article:

Suppose your code computes cos(x), then truncates that result and stores it into a temporary variable, say tmp. It might then compute cos(y), and (drum roll please) compare the untruncated result of cos(y) with tmp, that is, with the truncated result of cos(x).

When you store both results in variables (depending on optimization, etc.) there is a good chance that the result of the second cos calculation will also be stored in RAM before the calculation. Since the results will be truncated the same way, they will compare as ==.

Daniel
  • 6,595
  • 9
  • 38
  • 70