We can not compare binary floating point directly. I am writting a drop-in replacements class for float which override the bulti-in compare operators::
template<class U>
class Float {
private:
U val;
public:
Float(U v = 0): val(v) {}
operator U() const { return val; }
friend bool operator<(Float a, Float b) { return a.val + 1e-6 < b.val; }
friend bool operator==(Float a, Float b) { return !(a < b) && !(b < a); }
friend Float operator*(Float a, Float b) { return a.val * b.val; }
template<class T>
friend Float operator*(T a, Float b) { return a * b.val; }
template<class T>
friend Float operator*(Float a, T b) { return a.val * b; }
};
Now we can write something like this::
#include<assert.h>
int main() {
Float<double> a = 0.2, b = 0.02;
assert(a * a == 2 * b);
}
However, this code will show a unexpected behavior::
#include<complex>
int main() {
std::complex< Float<double> > a(0.2);
a * 2.0;
}
It will call Float::operator*(std::complex<Float<double> >, Float)
again and again
like a recursive endless loop, and finally get stack overflow.
How to fix this?
Edit
DeadMG and Charles Bailey point out that From ISO/IEC 14882:2011, 26.4: "The effect of instantiating the template complex for any type other than float, double, or long double is unspecified."
Maybe I have given a wrong counter example. We could still discuss how to write a good drop-in replacements class for fundamental type.
Let me clear my motivation, assert(0.1 * 0.1 == 0.01);
is counterintuitive. That is why I write a Float class which used "almost equal" behavior to compare two floating number.