4

I've come across a surprising oddity with floating point reciprocals that only seems to occur sometimes.

Why is it that, at unexpectable times, given two floats,

float a = ..., b = ...;

testing their equivalence at one time shows they're equal,

cout <&lt (a == b ? "T" : "F") &lt< endl; // prints T

yet, when adjusting the same line to test the equality of the reciprocals, and running the program no differently, they are suddenly not equal:

cout << (1/a == 1/b ? "T" : "F") << endl; // prints F

Here, a and b are not NaN, they're neither -INF nor +INF, and they're also not 0 (they're typically in the 3000 range with decimal values). I also noticed that, when compiling and running with both cout expressions somehow they then both print T.

Why would this be the case? I am very familiar with floating point numbers and related precision issues, but I would expect an operation on the same value to generate the same result. Or can division at times be a guesstimation/approximation instruction on certain CPUs?

Any clarification would be very appreciated.

EDIT:
As a side note, since I am starting to think this is something my compiler is doing, I am using MinGW32 GCC version 4.8.1. For targeting C++14 I'm using the flag -std=c++1y, as this version doesn't seem to support the -std=c++14 flag.

EDIT
Could this be a compiler error? I've determined that this is an issue in the GCC 4.8.1 compiler that occurs only when compiling with optimizations (-O2 or -O3).

Serge Dundich
  • 3,529
  • 2
  • 17
  • 15
Codesmith
  • 4,483
  • 4
  • 32
  • 43
  • 2
    A precise example of inputs that exhibit the behaviour is generally a good idea. – chris Jul 21 '18 at 03:02
  • I'm really trying, but I swear, I have the first quantum computer, because as long as I'm not looking at value, they aren't equal, and as soon as I do inspect them, they ARE equal. I'm even avoiding float-copying by inspecting them via uint32_t re-interpretation. – Codesmith Jul 21 '18 at 03:35
  • 1
    Most likely the answer is [this](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). One of the operands is probably more precise than the other and so they compare different. – NathanOliver Jul 21 '18 at 03:45
  • Agreed that it seems like that, @NathanOliver, but would/could that issue still occur if both numbers are floats, and I'm running the calculation with equivalent constant values, i.e. the `1` in `1/a` and `1/b`? – Codesmith Jul 21 '18 at 03:58
  • 1
    If you've found a bug, you should come up with a solid testcase that reproduces it in the question and post an answer with the details of the bug (and any workaround you might have). Such answers also often include a link to a bug report if it's logged in the compiler's bug tracker. – chris Jul 21 '18 at 04:51
  • 2
    @Codesmith Yes, it certainly can. The platform may only be able to keep one of the numbers in the higher precision because of register availability or the like. Don't compare floats for equality. – David Schwartz Jul 21 '18 at 04:54
  • Such is my plan, @chris, though it may take some time. David Schwartz, I fully agree, and for production I will likely just use an epsilon as a threshold. This question was really out of my curiosity as it was such a strange issue. – Codesmith Jul 21 '18 at 05:08
  • Yes that issue could happen. Do `float c = 1/a, d = 1/b;` and then compare c and d. If that works it tells you it is just a precision issue and just got floats work and not a bug. – NathanOliver Jul 21 '18 at 14:21

0 Answers0