¿Cómo se compara la flotación y el doble teniendo en cuenta la pérdida de precisión?

Resuelto Alex asked hace 16 años • 0 respuestas

¿ Cuál sería la forma más eficiente de comparar dos doubleo dos floatvalores?

Simplemente hacer esto no es correcto:

bool CompareDoubles1 (double A, double B)
{
   return A == B;
}

Pero algo como:

bool CompareDoubles2 (double A, double B) 
{
   diff = A - B;
   return (diff < EPSILON) && (-diff < EPSILON);
}

Parece desperdiciar el procesamiento.

¿Alguien conoce un comparador de flotadores más inteligente?

Alex avatar Aug 20 '08 09:08 Alex
Aceptado

Tenga mucho cuidado al utilizar cualquiera de las otras sugerencias. Todo depende del contexto.

He pasado mucho tiempo rastreando errores en un sistema que suponía a==bque si |a-b|<epsilon. Los problemas subyacentes fueron:

  1. La presunción implícita en un algoritmo de que si a==by b==centonces a==c.

  2. Usando el mismo épsilon para líneas medidas en pulgadas y líneas medidas en mils (0,001 pulgadas). Eso es a==bpero 1000a!=1000b. (Por eso AlmostEqual2sComplementpide el épsilon o max ULPS).

  3. ¡El uso del mismo épsilon tanto para el coseno de ángulos como para la longitud de líneas!

  4. Usar una función de comparación de este tipo para ordenar elementos en una colección. (En este caso, el uso del operador integrado de C++ ==para dobles produjo resultados correctos).

Como dije: todo depende del contexto y del tamaño esperado de ay b.

Por cierto, std::numeric_limits<double>::epsilon()es una "máquina épsilon". Es la diferencia entre 1.0y el siguiente valor representable por un doble. Supongo que podría usarse en la función de comparación, pero solo si los valores esperados son menores que 1. (Esto es en respuesta a la respuesta de @cdv...)

Además, si básicamente tiene intaritmética doubles(aquí usamos dobles para mantener valores int en ciertos casos), su aritmética será correcta. Por ejemplo 4.0/2.0será lo mismo que 1.0+1.0. Esto es siempre y cuando no hagas cosas que resulten en fracciones ( 4.0/3.0) o no salgan del tamaño de un int.

Andrew Stein avatar Sep 16 '2008 22:09 Andrew Stein

La comparación con un valor épsilon es lo que hace la mayoría de la gente (incluso en la programación de juegos).

Sin embargo, deberías cambiar un poco tu implementación:

bool AreSame(double a, double b)
{
    return fabs(a - b) < EPSILON;
}

Editar: Christer ha agregado una gran cantidad de información excelente sobre este tema en una publicación de blog reciente . Disfrutar.

OJ. avatar Aug 20 '2008 02:08 OJ.