2010-05-14 6 views
9

Y at-il dans la STL ou Boost un ensemble de fonctions de comparaison simples génériques?comparaison à virgule flottante en STL, BOOST

Celui que je trouve exigent toujours des paramètres du modèle, et/ou instanciation d'un modèle de struct .

Je cherche quelque chose avec une syntaxe comme:

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

pourrait être mis en œuvre qui comme:

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

EDIT: J'ai changé l'opérateur à l'égalité. (Voir les commentaires ci-dessous)

+1

Pourquoi voudriez-vous utiliser un epsilon pour comparer plus ou moins? – AshleysBrain

+3

La seule fois où une comparaison epsilon est nécessaire pour les types à virgule flottante ou double est pour la comparaison d'égalité '=='. plus ou moins n'a pas vraiment de sens avec epsilon, car qu'attendez-vous de la réponse quand ils sont égaux? si plus ou moins sont tous deux définis de la manière que vous mentionnez, puis dans le cas où ils sont égaux, vous obtiendrez un b = true et a == b = true, ce qui est incorrect. Le comportement correct est que ssi == b alors a> b = faux, et a Akanksh

+5

@Akanksh, La mise en œuvre ci-dessus peut ne pas être juste, mais les inégalités basées sur epsilon sont significatives et importantes pour précisément le scénario que vous mettez en évidence. Si deux nombres sont égaux selon un test '==' basé sur epsilon, alors vous avez aussi besoin d'un test '<' qui retourne false, même si le premier nombre est toujours un peu plus petit que le second. –

Répondre

9

Je ne sais pas d'une bibliothèque qu'il fait, peut-être parce qu'il est aussi simple comme une doublure ou peut-être parce qu'il a été oublié ...

Comme généralité va bien, vous êtes sûr que vous d aimez mettre en place l'epsilon pour un type donné à une valeur donnée ... tout au long de l'application? Personnellement, je voudrais le personnaliser en fonction des opérations que je fais (même si un défaut serait bien).

Quant à vos opérateurs, pourquoi ne pas les concevoir vous-même?

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

L'inégalité et supérieure à des méthodes peuvent être dérivées de manière triviale de cela.

Le paramètre supplémentaire signifie que vous voudrez peut-être spécifier une autre valeur pour un ensemble de calculs donné ... un cadre à l'échelle application est trop stricte.

+0

roughlte peut également être dérivé via un <=b <=>! (A> b) <=>! (B fulmicoton

+0

Oui, je voulais juste montrer la différence en comparant avec epsilon :) –

0

Depuis le commentaire de Marcelo Cantos:

... alors vous avez également besoin d'un test < qui renvoie false, même si le premier numéro est toujours aussi légèrement plus petit que le second.

J'imagine la mise en œuvre serait:

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

Cela ne répond pas à ma question. Quoi qu'il en soit, pourquoi vaut-il mieux mettre en œuvre de plus en plus d'égal par opposition à définir plus grand et ensuite définir moins et égal via? x y ! ((y> x) ou (x> y)) Y a-t-il un problème de performance? – fulmicoton

+0

Ce n'est pas. En général, vous définissez '<' et '==' séparément, même si '==' pourrait être dérivé (en théorie) de '<' en raison des performances. Ce qui est important est de préserver la relation logique bien ... –

1

Vous pouvez trouver des raisons de logique comparation "complexe" , dans la documentation de la bibliothèque de test d'amplification.

Questions connexes