Tengo una double variable llamada x.
En el código, x se les asigna un valor de 0.1 y comprobar en un ‘si’ declaración de la comparación de x y 0.1

if (x==0.1)
{
----
}

Por desgracia no entra en el if declaración

  1. Debo usar Double o double?

  2. ¿Cuál es la razón detrás de esto? Puedes sugerir una solución para esto?

14 Comentarios

  1. 92

    Es un problema estándar debido a cómo el equipo almacena los valores de punto flotante. Búsqueda de aquí para «punto flotante problema» y encontrarás toneladas de información.

    En corto un float/double no puede almacenar 0.1 precisamente. Siempre será un poco apagado.

    Puede intentar usar el decimal tipo que almacena los números en notación decimal. Por lo tanto 0.1 será representables con precisión.


    Lo que usted quería saber la razón:

    Float/double se almacenan como binario fracciones no decimales a fracciones. Para ilustrar:

    12.34 en notación decimal (lo que uso) significa

    1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2

    El equipo almacena los números de punto flotante de la misma manera, excepto que usa la base de 2: 10.01 significa

    1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2

    Ahora, usted probablemente sabe que hay algunos números que no pueden ser representados plenamente con nuestra notación decimal. Por ejemplo, 1/3 en notación decimal es 0.3333333…. Lo mismo sucede en notación binaria, excepto que los números que no pueden ser representados precisamente son diferentes. Entre ellos se encuentra el número de 1/10. En notación binaria que es 0.000110011001100….

    Desde la notación binaria no puede almacenar de forma precisa, se almacena en un redondeado manera. Por lo tanto su problema.

    • Estoy totalmente de entender lo que te dicen arriba. PERO, ¿por qué, si él escribió x = 0.01; para asignar x y, a continuación, en comparación con el literal 0.01, ¿no subyacente real valor binario de x y 0.01 ser el mismo (de nuevo, suponiendo que no hay cálculos se utiliza para asignar x). Por lo tanto, (x == 0.01) debería funcionar, no? Una vez que se realice algunas operaciones aritméticas con x, todas las apuestas están apagadas, sin embargo. También, yo he sido más explícito: if (x == 0.01d) explícitamente que 0.01 es un doble (y no la conversión de 0.01 de float a double)–que puede haber sido el problema.
    • no puedo reproducir lo que dicen(.NET 4). Puedo obtener true si comparo 0.01 con 0.01.
    • Sí, si usted x = 0.01; if ( x == 0.01), a continuación, la comparación debe ser cierto. Bien, asumiendo que no hay ningún implícito de flotación-a-doble de tipo de datos de conversiones (aunque tal vez incluso entonces). Pero el OP no especificar cómo consiguió el primer 0.01. Es muy probable que venga de un cálculo.
    • Cierto, el OP no indicar cómo la x valor fue asignado. Si el valor es asignado a través de cálculos iterativos (es decir, el resultado final es ~0.01), entonces esto podría ser «espera». 🙂
    • Para mí, es volver verdad? por qué?
    • Leer arriba.
    • Muchas gracias 🙂
    • if(scheduledEnqueueTimeInMin != 0){ } donde scheduledEnqueueTimeInMin es asignado como bool scheduledEnqueueTimeInMin=0 al comprobar como el de arriba, yo estoy por debajo de sonar problema Do not check floating point inequality with exact values, use a range instead.

  2. 39

    double y Double son los mismos (double es un alias para Double) y pueden ser utilizados indistintamente.

    El problema con la comparación de una habitación doble con otro valor es que los dobles son valores aproximados, no exactos valores. Así que cuando se establece x a 0.1 que en realidad puede ser almacenado como 0.100000001 o algo por el estilo.

    Lugar de la comprobación de la igualdad, se debe verificar que la diferencia es menor que una mínima diferencia (tolerancia). Algo así como:

    if (Math.Abs(x - 0.1) < 0.0000001)
    {
        ...
    }
  3. 19

    Necesita una combinación de Math.Abs en X-Y y un value para comparar.

    Puede utilizar el siguiente método de Extensión enfoque

    public static class DoubleExtensions
        {
            const double _3 = 0.001;
            const double _4 = 0.0001;
            const double _5 = 0.00001;
            const double _6 = 0.000001;
            const double _7 = 0.0000001;
    
            public static bool Equals3DigitPrecision(this double left, double right)
            {
                return Math.Abs(left - right) < _3;
            }
    
            public static bool Equals4DigitPrecision(this double left, double right)
            {
                return Math.Abs(left - right) < _4;
            }
    
            ...

    Ya que raras veces llamar a los métodos de doble excepto ToString creo que es muy segura de extensión.

    A continuación, usted puede comparar x y y como

    if(x.Equals4DigitPrecision(y))

    • Podría ser agradable extensión a Doble struct !
  4. 10

    La comparación de número de punto flotante, no siempre se puede hacer, precisamente a causa de redondeo. Para comparar

    (x == .1)

    el equipo realmente se compara

    (x - .1) vs 0

    Resultado de sybtraction no siempre puede ser represeted precisamente por la forma en número de punto flotante se representan en la máquina. Por lo tanto, obtener algún valor distinto de cero y la condición se evalúa a false.

    Para superar esta comparar

    Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
    • Podría ilustrar claramente con un ejemplo??? ¿Cuál es la solución, así que necesito cambiar mi estado de cuenta??
  5. 5

    De la documentación:

    Precisión en las Comparaciones
    El método Equals debe ser utilizado con precaución, debido a que los dos aparentemente equivalentes valores pueden ser desiguales, debido a la diferente precisión de los dos valores. En el ejemplo siguiente se informa de que el valor Doble .3333 y el Doble devuelto dividiendo 1 por 3 son desiguales.

    Lugar de comparar para la igualdad, una técnica recomendada implica la definición de un margen aceptable de la diferencia entre los dos valores (como .01% de uno de los valores). Si el valor absoluto de la diferencia entre los dos valores es menor o igual al margen, la diferencia es probable que sea debido a las diferencias en la precisión y, por lo tanto, los valores son propensos a ser igual. En el ejemplo siguiente se utiliza esta técnica para comparar .33333 y 1/3, los dos valores que en el ejemplo de código anterior se encontró a ser desigual.

    Así que si usted realmente necesita un doble, debe utilizar la técnica se describe en la documentación.
    Si se puede, cambiar a un decimal. Que’ va a ser más lento, pero usted no tiene este tipo de problema.

  6. 3

    Comparación exacta de los valores de punto flotante se sabe que no siempre funciona debido al redondeo y a la representación interna del problema.

    Intentar imprecisa comparación:

    if (x >= 0.099 && x <= 0.101)
    {
    }

    La otra alternativa es utilizar el tipo de datos decimal.

  7. 2

    Uso decimal. No tiene este «problema».

    • Las operaciones con valores decimales son mucho más lento. No debemos utilizar siempre el tipo de decimal sólo porque «no tiene este problema». Ambas alternativas tienen sus propios usos.
  8. 1

    Doble (llamado flotar en algunos idiomas) es fraut con problemas debido a problemas de redondeo, es bueno sólo si usted necesita valores aproximados.

    El tipo de datos Decimal no lo que desea.

    De referencia decimales y decimales son los mismos .NET C#, como son el doble y el Doble de tipos, ambos se refieren al mismo tipo (decimal y doble son muy diferentes, aunque, como hemos visto).

    Ten en cuenta que el tipo de datos Decimal tiene algunos costos asociados con ella, así que úselo con precaución si usted está buscando en bucles, etc.

  9. 1

    Tomar la punta desde el código Java de la base, trate de usar .CompareTo y de prueba para el cero de comparación. Esto supone la .CompareTo función toma en cuenta el punto flotante de la igualdad de una manera exacta. Por ejemplo,

    System.Math.PI.CompareTo(System.Math.PI) == 0

    Este predicado debe devolver true.

    • Esto no es correcto. CompareTo simplemente utiliza ==, propenso a errores de redondeo
  10. 0

    Como regla general:

    Doble representación es bastante bueno en la mayoría de los casos, pero puede fallar miserablemente en algunas situaciones. Utilizar valores decimales si usted necesita completar precisión (como en aplicaciones financieras).

    La mayoría de los problemas con los dobles no viene de la comparación directa, el uso de la informática para ser un resultado de la acumulación de varias operaciones matemáticas que exponencialmente perturbar el valor debido al redondeo de fracciones y de los errores (especialmente con multiplicaciones y divisiones).

    Comprobar su lógica, si el código es:

    x = 0.1
    
    if (x == 0.1)

    que no debe fallar, es a simple error, si el valor de X se calcula por el más complejo de los medios o de las operaciones es muy posible que el método ToString utilizado por el depurador está usando un smart redondeo, tal vez usted puede hacer lo mismo (si eso es demasiado arriesgado volver a usar decimal):

    if (x.ToString() == "0.1")
  11. 0

    número de punto flotante representaciones son notoriamente inexactas (porque de la manera en que los flotadores se almacenan internamente) por ejemplo, x puede ser en realidad 0.0999999999 o 0.100000001 y su condición de error. Si desea determinar si los flotadores son iguales que usted necesita específico si son iguales dentro de una cierta tolerancia.

    es decir,

    if(Math.Abs(x) - 0.1 < tol) {
       //Do something 
    }
    • Y tirar en una de Matemáticas.Abs, en el caso de que x es un poco menor que 0.1. El código aceptará x== -10.
  12. 0
    //number of digits to be compared    
    public int n = 12 
    //n+1 because b/a tends to 1 with n leading digits
    public double Epsilon { get; } = Math.Pow(10, -(n+1)); 
    
    public bool IsEqual(double a, double b)
    {
        if (Math.Abs(a)<= double.Epsilon || Math.Abs(b) <= double.Epsilon)
            return Math.Abs(a - b) <=  double.Epsilon;
        return Math.Abs(1.0 - a / b) <=  Epsilon;
    }

Dejar respuesta

Please enter your comment!
Please enter your name here