Double.Epsilon por la igualdad, mayor que, menor que, menor que o igual a, mayor que o igual a

StackOverflow https://stackoverflow.com/questions/2411392

  •  18-09-2019
  •  | 
  •  

Pregunta

http://msdn.microsoft.com/en- es / library / system.double.epsilon.aspx

  

Si crea un algoritmo personalizado que   Determina si dos de punto flotante   los números pueden ser consideradas iguales, se   debe utilizar un valor que es mayor que   la constante de Epsilon para establecer la   margen absoluto aceptable de   diferencia para los dos valores que se   consideran iguales. (Normalmente, que   margen de diferencia es muchas veces   mayor que Epsilon.)

Así es que esto no es realmente un épsilon que podría ser utilizado para las comparaciones? No entiendo muy bien la redacción de MSDN.

¿Puede ser utilizado como el épsilon en los ejemplos aquí? - ¿Cuál es la forma más eficaz para float y double comparación ?

Y finalmente esto parece muy importante así que me gustaría para asegurarse de que tengo una aplicación sólida para la igualdad, mayor que, menor que, menor que o igual a, y mayor o igual a.

¿Fue útil?

Solución

No sé lo estaban echando humo cuando escribieron eso. Double.Epsilon es el valor del punto pequeño que puede representarse no denormal flotante que no es 0. Todo lo que sabes es que, si hay un error de truncamiento, que siempre será mayor que este valor. Mucho más grande.

El tipo System.Double puede representar valores precisos para hasta 15 dígitos. Así que un simple primera estimación orden si un valor x doble es igual a una constante es utilizar un épsilon de constante * 1E-15

public static bool AboutEqual(double x, double y) {
    double epsilon = Math.Max(Math.Abs(x), Math.Abs(y)) * 1E-15;
    return Math.Abs(x - y) <= epsilon;
}

Se tiene que tener cuidado, sin embargo, los errores de truncamiento se pueden acumular. Si tanto x y y se calculan los valores a continuación, usted tiene que aumentar la épsilon.

Otros consejos

  

Me gustaría asegurarse de que tengo una aplicación sólida para la igualdad, mayor que, menor que, menor que o igual a, y mayor o igual a.

Está utilizando aritmética de punto flotante binario.

aritmética binaria de punto flotante fue diseñado para representar cantidades físicas, como la longitud, masa, carga, tiempo, y así sucesivamente.

Es de suponer entonces que está utilizando la aritmética de coma flotante binario, ya que estaba destinado a ser utilizado:. Hacer aritmética de las cantidades físicas

Las mediciones de las magnitudes físicas siempre tienen una precisión particular, dependiendo de la precisión del aparato utilizado para medir ellos.

Dado que usted es el que proporciona los valores de las cantidades que está manipulando, que es el único que sabe lo que los "barras de error son" en esa cantidad. Por ejemplo, si usted está proporcionando la cantidad "de la altura del edificio es de 123,56 metros" entonces usted sabe que esto es exacto al centímetro, pero no hasta el micrómetro.

Por lo tanto, cuando se comparan dos cantidades para la igualdad, la semántica deseada es decir "son estas dos cantidades iguales dentro de las barras de error especificados por cada medición?"

Así que ahora tenemos una respuesta a su pregunta. Lo que debe hacer es no perder de vista lo que el error está en cada cantidad; por ejemplo, la altura del edificio es "dentro de 0,01 metros de 123.56" porque sabe que es el grado de precisión de la medición es. Si a continuación, obtener otra medición que es 123.5587 y desea saber si las dos medidas son "iguales" dentro de las tolerancias de error, y luego hacer la resta y ver si cae en la tolerancia de error. En este caso lo hace. Si las mediciones fueron de hecho precisa al micrómetro, a continuación, que no son iguales.

En resumen: usted es la única persona que sabe lo tolerancias de error son sensibles, porque usted es la única persona que sabe dónde están las figuras está manipulando vinieron de en el primer lugar. Use cualquier tolerancia de error tiene sentido para sus mediciones dada la precisión del equipo que utilizó para producirla.

Si usted tiene dos valores dobles que están cerca de 1.0, pero difieren en sólo sus bits menos significativos, entonces la diferencia entre ellas será en muchos órdenes de magnitud mayor que Double.Epsilon. De hecho, la diferencia es de 324 órdenes decimales de magnitud. Esto es debido al efecto de la porción de exponente. Double.Epsilon tiene una enorme exponente negativo en él, mientras que 1,0 tiene un exponente de cero (después de los sesgos se eliminan, por supuesto).

Si desea comparar dos valores similares para la igualdad, entonces usted tendrá que elegir un valor épsilon personalizado que es apropiado para el tamaño órdenes de magnitud de los valores a comparar.

Si los valores dobles que se están comparando son cerca de 1.0. A continuación, el valor del bit menos siginificant estaría cerca ,0000000000000001. Si los valores dobles que se están comparando están en los miles de billones, entonces el valor del bit menos significativo podría ser tanto como un millar. Ningún valor único para épsilon podría ser utilizado para las comparaciones de igualdad en esas dos circunstancias.

Me acabo de hacer esto -. Utilizando idea Kent bogarts

private bool IsApproximatelyEqual(double x, double y, double acceptableVariance)
{
     double variance = x > y ? x - y : y - x;
     return variance < acceptableVariance;

     //or
     //return Math.Abs(x - y) < acceptableVariance;
}

Podría ser utilizado para las comparaciones, asumiendo que usted quiere asegurarse de que los dos valores son o bien exactamente iguales, o tienen la diferencia representable más pequeño para el tipo doble. En términos generales, se desea utilizar un número mayor que double.Epsilon para comprobar si dos dobles son aproximadamente iguales.

¿Por qué el marco .NET no define algo como

bool IsApproximatelyEqual(double value, double permittedVariance);

es más allá.

Creo que los bits correspondientes en el enlace de MSDN informados son las siguientes:

  

Sin embargo, la propiedad no es un Epsilon   medida general de la precisión de la   tipo doble; sólo se aplica a Doble   instancias que tienen un valor de cero.

     

Nota: El valor de la Epsilon   propiedad no es equivalente a la máquina   epsilon, que representa la parte superior   unido del error relativo debido a   redondeo en aritmética de punto flotante.

     

Este valor no se define como más pequeña   número positivo x, tal que x + 1.0   no es igual a 1,0, por lo Double.Epsilon   No se puede utilizar para "casi igualdad".   No existe ninguna constante en el   marco cuyo valor es más pequeño   número positivo x, tal que x + 1.0   no es igual a 1.0.

Tengo que decir, que me sorprende. Yo también había asumido que Double.Epsilon era el equivalente de DBL_EPSILON en C / C ++ - claro que no!

Por lo que puedo leer de ese vínculo parece estar diciendo 'que necesita averiguar un valor decente mismo para las comparaciones', que es bastante sorprendente por decir lo menos.
Tal vez alguien más bien informado puede aclarar:)

Yo uso el siguiente

public static class MathUtil {
    /// <summary>
    /// smallest such that 1.0+EpsilonF != 1.0
    /// </summary>
    public const float EpsilonF = 1.192092896e-07F;

    /// <summary>
    /// smallest such that 1.0+EpsilonD != 1.0
    /// </summary>
    public const double EpsilonD = 2.2204460492503131e-016;

    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    public static bool IsZero( this double value ) {
        return value < EpsilonD && value > -EpsilonD;
    }

    [MethodImpl( MethodImplOptions.AggressiveInlining )]
    public static int Sign( this double value ) {
        if ( value < -EpsilonD ) {
            return -1;
        }
        if ( value > EpsilonD )
            return 1;
        return 0;
    }

y si desea comprobar la igualdad de dos dobles 'a' y 'b', puede utilizar

(a-b).IsZero();

y si desea obtener el resultado de la comparación, utilice

(a-b).Sign();

El problema con la comparación de los dobles es que cuando se hace una comparación entre dos resultados matemáticos diferentes que son iguales, pero que, debido a errores de redondeo, no están evaluando al mismo valor, van a tener cierta diferencia ... que es más grande que épsilon, excepto en casos extremos. Y el uso de un valor épsilon fiable también es difícil. Algunas personas consideran dos dobles iguales si la diferencia entre ellos es menor que un valor porcentual, ya que con una mínima diferencia épsilon estática puede significar sus diferencias son demasiado pequeño o grande cuando el doble en sí es alta o baja.

Aquí hay un código que incluía dos veces en el Juego de Herramientas de Control de Silverlight:

    public static bool AreClose(double value1, double value2)
    {
        //in case they are Infinities (then epsilon check does not work)
        if(value1 == value2) return true;
        // This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON
        double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
        double delta = value1 - value2;
        return(-eps < delta) && (eps > delta);
    }

En un lugar que utilizan para 1e-6 épsilon; en otro que utilizan 1.192093E-07. Usted tendrá que elegir su propio épsilon.

No hay otra opción que usted tiene que calcular por sí mismo o definir propia constante.

double calculateMachineEpsilon() {
    double result = 1.0;
    double one = 1.0/256;

    while(one + result/2.0 != 1.0) {
        result/=2.0;
    }
    return result;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top