2010-05-14 13 views
9

¿Hay en el STL o en Boost un conjunto de funciones simples de comparación genéricas?Comparación de punto flotante en STL, BOOST

El que encontré siempre requieren parámetros de plantilla y/o instanciación de una plantilla de estructura .

estoy buscando algo con una sintaxis como:

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

que podría ser implementado como:

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

EDIT: He cambiado el operador de igualdad. (Ver comentarios abajo)

+1

¿Por qué usaría un épsilon para comparar mayor o menor? – AshleysBrain

+3

El único momento en que se necesita una comparación epsilon para coma flotante o tipos dobles es para la comparación de igualdad '=='. más o menos realmente no tienen ningún significado con épsilon, porque ¿qué esperas que sea la respuesta cuando son iguales? si mayor o menor se definen ambos en la forma que usted menciona, entonces en el caso en que sean iguales, obtendrá un b = verdadero y a == b = verdadero, que es incorrecto. El comportamiento correcto es que iff a == b entonces a> b = falso, y a Akanksh

+5

@Akanksh, la implementación anterior puede no ser correcta, pero las desigualdades basadas en épsilon son significativas e importantes precisamente para el escenario que resalta. Si dos números son iguales de acuerdo con una prueba '==' basada en épsilon, entonces también necesita una prueba '<' que devuelve falso, incluso si el primer número es ligeramente menor que el segundo. –

Respuesta

9

no sé de cualquier biblioteca que lo hace, tal vez porque es tan simple como una sola línea o tal vez porque se olvida ...

Como generalidad va sin embargo, está seguro de que' Me gusta configurar el épsilon para un tipo dado a un valor dado ... ¿a lo largo de la aplicación? Personalmente, me gustaría personalizarlo en función de las operaciones que estoy realizando (aunque un valor predeterminado sería bueno).

En cuanto a sus operadores, ¿por qué no idearlos usted mismo?

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 desigualdad y más que los métodos se pueden derivar trivialmente de esto.

El parámetro adicional significa que puede desear especificar otro valor para un conjunto dado de cálculos ... una configuración de toda la aplicación es demasiado estricta.

+0

roughlte también se puede derivar a través de un <=b <=>! (A> b) <=>! (B fulmicoton

+0

Sí, yo sólo quería mostrar la diferencia en comparación con épsilon :) –

0

Desde el comentario de Marcelo Cantos:

... entonces también necesita una prueba que < vuelve falsa, incluso si el primer número es siempre tan ligeramente más pequeña que el segundo.

Me imagino que la implementación sería:

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

Eso no responde mi pregunta. De todos modos por qué es mejor para implementar mayor y menor de la misma por oposición a la definición de una mayor definición y luego a través de menos e igual? x y ! ((Y> x) o (x> y)) ¿Hay algún problema de rendimiento? – fulmicoton

+0

No lo es. En general, se definen '<' y '==' por separado, aunque '==' podría derivarse (en teoría) de '<' por el rendimiento. Lo que es importante es preservar la relación lógica aunque ... –

1

se puede encontrar algunas de las razones de la lógica comparacion "complejo" , en la documentación de la biblioteca de prueba de impulso.

Cuestiones relacionadas