Look at this program:
#include <iostream>
#include <cmath>
using namespace std;
typedef pair<int, int> coords;
double dist(coords a, coords b)
{
return sqrt((a.first - b.first) * (a.first - b.first) +
(a.second - b.second) * (a.second - b.second));
}
int main()
{
coords A = make_pair(1, 0);
coords B = make_pair(0, 1);
coords C = make_pair(-1, 0);
coords D = make_pair(0, -1);
cerr.precision(20);
cerr << dist(A, B) + dist(C, D) << endl;
cerr << dist(A, D) + dist(B, C) << endl;
if(dist(A, B) + dist(C, D) > dist(A, D) + dist(B, C))
{
cerr << "*" << endl;
}
return 0;
}
Function dist returns distance betweeen two points. A, B, C, D are corners of square.
It should be dist(A, B) == dist(B, C) == dist(C, D) == dist(D, A) == sqrt(2).
And dist(A, B) + dist(C, D) == dist(A, D) + dist(B, C) == 2 * sqrt(2)
I am using GNU/Linux, i586, GCC 4.8.2.
I compile this program and run:
$ g++ test.cpp ; ./a.out
2.8284271247461902909
2.8284271247461902909
*
We see, that program outputs equal values of dist(A, B) + dist(C, D) and dist(A, D) + dist(B, C), but condition dist(A, B) + dist(C, D) > dist(A, D) + dist(B, C) is true!
When I compile with -O2, its look OK:
$ g++ test.cpp -O2 ; ./a.out
2.8284271247461902909
2.8284271247461902909
I think, it is a gcc-bug, and it is not directly related to floating-point operation accuracy, because in this case values dist(A, B) + dist(C, D) and dist(A, D) + dist(B, C) MUST BE equal (each of them is sqrt(2) + sqrt(2)).
When I change function dist:
double dist(coords a, coords b)
{
double x = sqrt((a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second));
return x;
}
the program runs correct. So the problem not in floating-point representation of numbers, but in the gcc code.
Edit:
Simplified example for 32-bit compiler:
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
if (sqrt(2) != sqrt(2))
{
cout << "Unequal" << endl;
}
else
{
cout << "Equal" << endl;
}
return 0;
}
Run without optimization:
$ g++ test.cpp ; ./a.out
Unequal
Run with -ffloat-store:
$ g++ test.cpp -ffloat-store ; ./a.out
Equal
Solution:
Probably, it is "not a bug" in GCC #323: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323
Compiling with -ffloat-store solve the problem.