2016-09-15 15 views
-2

GCC 4.6.1とVisual Studio(2008 & 2012)またはOSXのClang 7.3.0との間で予期しない(そして不正確な)不等式の比較が発生することがわかりました。コンパイラの最適化による偽浮動の不等式?

ここで減少抜粋です:

typedef float ftype; 
struct Foo 
{ 
    ftype v; 

    Foo(): v(16.0f/60.0f) {} 
    ftype val() const {return v * 60.0f;} 
}; 

void bar() 
{ 
    Foo f; 
    ftype v = f.val(); 
    if (v != f.val()) 
     printf("inequal"); 
} 

FTYPEがdoubleとしてtypedefされている場合、問題は発生しませんが。これはコンパイラのインライン展開と関係がありますか?おそらく実際には浮動小数点の代わりに二重を返すでしょうか?

+0

関連:http://stackoverflow.com/questions/29335982/floating-point-computation-changes-if-stored-in-intermediate-double-variable –

+0

私はこれが浮動小数点数学壊れていますか?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken)または[中間二重変数に格納されている場合は浮動小数点計算の変更](http://stackoverflow.com/questions/ 29335982 /中間浮動小数点変数に格納される浮動小数点演算の変更。この場合、正確に同じ関数を2回呼び出して、関数の戻り値の型とまったく同じ型の変数に格納しますが、それでもequal *をそれ自身と比較しません*。 –

+0

これは重複していないことに同意します。関係する式と値はまったく同じで、型昇格のない浮動小数点のみであり、同じ結果が得られるはずです。 – doug

答えて

1

スニペットでは、単純な「==」または「!=」を使用して、2つの実数(浮動小数点数または2倍数)を互いに等しくなるように効果的に比較します。残念ながら、このようなアプローチは、浮動小数点演算が行われるため実数ではうまく機能しません。すなわち、実数は、整数に比べてメモリに正確にに格納されません。

許容誤差を考慮した2つの実数を比較する必要があります。この許容差は、使用するタイプ(フロートまたはダブル)と機械によって異なります。

以下のような単純なソリューションは機能するかもしれませんが、テンプレートベースのコードに統合する必要があります。

#include<limits> 
#include<cmath> 

TOL=std::numeric_limits<float>::epsilon() 
if (std::abs(v - f.val())<TOL) 
{ 
    //some code 
} 

Floating-Point Guideをご覧ください。 StackOverflowの上のそれらの答えにも役立つはずです:

How to correctly and standardly compare floats?

What is the most effective way for float and double comparison?

UPD:バグ代わりに@ダグさんのコメントごとに修正ABS値だけ差を利用して。

+2

差分の絶対値と比較する必要があります。それは一方向の誤りに対してのみ働く。 – doug

関連する問題