Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

x*x != x*x in auto-variable?

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.
like image 842
Stefan Pochmann Avatar asked Jan 26 '26 18:01

Stefan Pochmann


1 Answers

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.

like image 190
1201ProgramAlarm Avatar answered Jan 28 '26 07:01

1201ProgramAlarm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!