2010-05-14 9 views
9

Czy w zestawie STL lub w boost znajduje się zestaw ogólnych prostych funkcji porównania?Porównywanie zmiennoprzecinkowe w STL, BOOST

Ten, który znalazłem, zawsze wymaga parametrów szablonu i/lub utworzenia szablonu struktury .

szukam czegoś o składni jak:

if (is_equal(x,y)) 
{ 
    ... 
} 

które mogą być realizowane jako:

template <typename T> 
bool is_equal(const T& x, const T& y) 
{ 
    return (fabs(x - y) < Precision<T>::eps); 
} 

EDIT: Zmieniłem operatora równe. (Patrz komentarz poniżej)

+1

Po co używać epsilon do porównywania większych lub mniejszych? – AshleysBrain

+3

Jedyny przypadek, w którym porównanie epsilon jest potrzebne dla zmiennoprzecinkowych lub podwójnych typów, to porównanie równości "==". więcej lub mniej nie ma żadnego znaczenia w epsilon, ponieważ czego oczekujesz odpowiedzi, gdy są równe? jeśli większe lub mniejsze są zdefiniowane w sposób, o którym wspomniałeś, to w przypadku, gdy są one równe, otrzymasz b = true i a == b = true, co jest nieprawidłowe. Prawidłowe zachowanie polega na tym, że iff a == b, a> b = fałsz, a a Akanksh

+5

@Akanksh, Powyższa implementacja może nie mieć racji, ale nierówności na bazie epsilon mają znaczenie i są ważne dla precyzyjnego scenariusza, który podkreślasz. Jeśli dwie liczby są równe według testu '==' opartego na epsilon, to potrzebujesz również testu '<', który zwraca wartość false, nawet jeśli pierwsza liczba jest zawsze trochę mniejsza od drugiej. –

Odpowiedz

9

nie wiem o wszelkich biblioteki, która robi to, być może dlatego, że jest tak proste, jak jeden-liner, a może dlatego, że została zapomniana ...

Jak ogólność idzie jednak, czy na pewno” Czy chcesz ustawić epsilon dla jednego danego typu przy danej wartości ... w całej aplikacji? Osobiście chciałbym go dostosować w zależności od operacji, które wykonuję (nawet jeśli domyślnie byłoby miło).

Co do operatorów, dlaczego nie samodzielnie je opracować?

template <class T> 
bool rough_eq(T lhs, T rhs, T epsilon = Precision<T>::epsilon) // operator== 
{ 
    return fabs(lhs - rhs) < epsilon; 
} 

template <class T> 
bool rough_lt(T lhs, T rhs, T epsilon = Precision<T>::epsilon) // operator< 
{ 
    return rhs - lhs >= epsilon; 
     // tricky >= because if the difference is equal to epsilon 
     // then they are not equal per the rough_eq method 
} 

template <class T> 
bool rough_lte(T lhs, T rhs, T epsilon = Precision<T>::epsilon) // operator<= 
{ 
    return rhs - lhs > -epsilon; 
} 

Nierówności i większe niż metody mogą być trywialnie wyprowadzone z tego.

Dodatkowy parametr oznacza, że ​​można podać inną wartość dla danego zestawu obliczeń ... ustawienie dla całej aplikacji jest zbyt surowe.

+0

roughlte można również uzyskać poprzez a <=b <=>! (A> b) <=>! (B fulmicoton

+0

Tak, chciałem tylko pokazać różnicę w porównaniu z epsilon :) –

0

Od komentarzu Marcelo Cantos:

... to trzeba również < test, który zwraca false, nawet jeśli pierwszy liczba jest wciąż tak nieco mniejsze niż sekunda.

wyobrażam sobie wdrożenie byłoby:

return !roughly_equal(a, b) && a < b; 
+0

To nie odpowiada na moje pytanie. W każdym razie, dlaczego lepiej jest realizować większe i mniejsze od równości przeciwieństwo do definiowania większej, a następnie definiowania mniejszego i równego przez? x y ! ((y> x) lub (x> y)) Czy jest jakiś problem z wydajnością? – fulmicoton

+0

To nie jest. Ogólnie definiujesz '<' i '==' oddzielnie, nawet jeśli '==' może być wyprowadzone (teoretycznie) z '<' z powodu wydajności. Ważne jest, aby zachować logiczną zależność ... –

1

Można znaleźć kilka przyczyn „kompleks” komparacji logiki , w dokumentacji testowej biblioteki Boost.