2 進浮動小数点を直接比較することはできません。私は一括比較演算子をオーバーライドする float のドロップイン置換クラスを書いています::
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; }
};
これで、次のように書くことができます::
#include<assert.h>
int main() {
Float<double> a = 0.2, b = 0.02;
assert(a * a == 2 * b);
}
ただし、このコードは予期しない動作を示します::
#include<complex>
int main() {
std::complex< Float<double> > a(0.2);
a * 2.0;
}
再帰的な無限ループのように何度も呼び出さFloat::operator*(std::complex<Float<double> >, Float)
れ、最終的にスタック オーバーフローが発生します。これを修正する方法は?
編集
DeadMG と Charles Bailey は、ISO/IEC 14882:2011、26.4 から次のように指摘しています。
多分私は間違った反例を与えました。基本型の適切なドロップイン置換クラスを作成する方法については、まだ議論できます。
私の動機を明確にさせてください、assert(0.1 * 0.1 == 0.01);
直感に反しています。そのため、「ほぼ等しい」動作を使用して 2 つの浮動小数点数を比較する Float クラスを作成します。