2010-05-14 13 views
9

Esiste in STL o Boost un set di funzioni di confronto semplici generiche?Confronto a virgola mobile in AWL, BOOST

Quello che ho trovato richiede sempre i parametri del modello e/o l'istanziazione di un modello di struttura .

Sto cercando qualcosa con una sintassi simile:

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

che potrebbero essere attuate come:

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

EDIT: Ho cambiato l'operatore alla parità. (Vedi commenti qui sotto)

+1

Perché dovresti usare un epsilon per confrontare più o meno? – AshleysBrain

+3

L'unico momento in cui un confronto epsilon è necessario per virgola mobile o doppio è per il confronto dell'uguaglianza '=='. più o meno non hanno alcun significato con epsilon, perché cosa ti aspetti che la risposta sia quando sono uguali? se più o meno sono entrambi definiti nel modo in cui ne parli, allora nel caso in cui siano uguali, otterrai b = true e a == b = true, che non è corretto. Il comportamento corretto è che iff a == b then a> b = false e a Akanksh

+5

@Akanksh, L'implementazione sopra potrebbe non essere corretta, ma le disuguaglianze basate su epsilon sono significative e importanti per lo scenario che evidenziate. Se due numeri sono uguali secondo un test '==' basato su epsilon, allora hai bisogno anche di un test <

risposta

9

non so di qualsiasi libreria che lo fa, forse perché è semplice come un one-liner o forse perché è stato dimenticato ...

Come generalità va, però, sei sicuro' d come impostare l'epsilon per un dato tipo ad un determinato valore ... in tutta l'applicazione? Personalmente mi piacerebbe personalizzarlo a seconda delle operazioni che sto facendo (anche se un default sarebbe bello).

Per quanto riguarda gli operatori, perché non progettarli da soli?

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; 
} 

La disuguaglianza e maggiore dei metodi può essere banalmente derivata da questo.

Il parametro aggiuntivo indica che è possibile che si desideri specificare un altro valore per un determinato insieme di calcoli ... un'impostazione a livello di applicazione è troppo rigida.

+0

roughlte può anche essere derivata tramite a <=b <=>! (A> b) <=>! (B fulmicoton

+0

Sì, volevo solo mostrare la differenza nel confronto con epsilon :) –

0

Dal commento di Marcelo Cantos:

... allora è necessario anche un test di < che restituisce false, anche se il primo numero è sempre così leggermente più piccolo rispetto al secondo.

mi immagino l'attuazione sarebbe:

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

Questo non risponde alla mia domanda. In ogni caso, perché è meglio attuare una maggiore e meno uguale da un'opposizione a definire maggiore e quindi definire meno e uguale via? x y ! ((y> x) o (x> y)) C'è qualche problema di prestazioni? – fulmicoton

+0

Non lo è. In generale definisci '<' e '==' separatamente anche se '== 'potrebbe essere derivato (in teoria) da' <'a causa delle prestazioni. Ciò che è importante è preservare la relazione logica però ... –

1

si potrebbe trovare alcune ragioni della logica comparazione "complesso" , nella documentazione della libreria di test spinta.