3

How does x * x get changed by storing it in an "auto variable"? I think it should still be the same, and my tests show that the types, the sizes, and the values apparently all are the same.

But even x * x == (xx = x * x) is false. What the hell?

(Note: I know IEEE 754 and how float and double work and their usual issues, but this one baffles me.)

#include <iostream>
#include <cmath>
#include <typeinfo>
#include <iomanip>
using namespace std;

int main() {
    auto x = sqrt(11);
    auto xx = x * x;
    cout << boolalpha << fixed << setprecision(130);
    cout << "   xx == 11           " << (   xx == 11          ) << endl;
    cout << "x * x == 11           " << (x * x == 11          ) << endl;
    cout << "x * x == xx           " << (x * x == xx          ) << endl;
    cout << "x * x == (xx = x * x) " << (x * x == (xx = x * x)) << endl;
    cout << "x * x == x * x        " << (x * x == x * x       ) << endl;
    cout << "types        " << typeid(xx).name() << " " << typeid(x * x).name() << endl;
    cout << "sizeofs      " << sizeof(xx) << " " << sizeof(x * x) << endl;
    cout << "xx           " << xx    << endl;
    cout << "x * x        " << x * x << endl;
}

Here's the output:

   xx == 11           true
x * x == 11           false
x * x == xx           false
x * x == (xx = x * x) false
x * x == x * x        true
types        d d
sizeofs      8 8
xx           11.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
x * x        11.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Compiled with this:

C:\Stefan\code\leetcode>g++ test4.cpp -static-libstdc++ -std=c++11 -o a.exe

C:\Stefan\code\leetcode>g++ --version
g++ (GCC) 4.8.1
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Stefan Pochmann
  • 27,593
  • 8
  • 44
  • 107
  • 1
    This has nothing to do with `auto`. All your variables are deduced as `double`s, it's just a matter of floating point precision. See e.g. [this](http://stackoverflow.com/questions/14151740/sqrt-perfect-squares-and-floating-point-errors). – vsoftco Feb 17 '16 at 04:30
  • 2
    Unrelated, but you can print `bools` as `true` or `false` using `std::cout<< std::boolalpha;`. That will save you some code. – juanchopanza Feb 17 '16 at 04:31
  • @juanchopanza Thanks, used that now. – Stefan Pochmann Feb 17 '16 at 04:45
  • @vsoftco Your link doesn't seem to explain this. Does it really? – Stefan Pochmann Feb 17 '16 at 04:47
  • @vsoftco The question there is quite different and none of the answers there explain my issue. Looks like you don't understand my question. – Stefan Pochmann Feb 17 '16 at 04:58

1 Answers1

6

This is the usual imprecision with doubles. You don't mention your hardware, but on x86 (32 bit Intel) the temporaries used during calculations are 10 byte long doubles. The x * x will be one of those, while the xx = x * x will be stored to an 8 byte double before being loaded back into the FPU for the compare.

You may get different results if you turn optimizations on, or build a 64 bit executable.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56