Cómo (portablemente) obtener DBL_EPSILON en C y C++

1 minuto de lectura

avatar de usuario
vehomzzz

Estoy usando GCC 3.4 en Linux (AS 3) y estoy tratando de averiguar cómo obtener DBL_EPSILON, o al menos una aproximación decente. ¿Cómo puedo obtenerlo programáticamente?

  • Relacionado stackoverflow.com/questions/1217284/… y

    – Sinan Ünür

    14 de octubre de 2009 a las 17:34

  • Una cosa de la que nadie habló a continuación y que es importante: cualquier definición del valor de Epsilon es una apuesta que sale de la nada (o casi). Quiero decir, este es un valor razonable definido para cálculos razonables. La naturaleza misma de los reales en las computadoras es que no son valores exactos (bin vs dec). Entonces, cualquier cálculo amplía la brecha entre los valores calculados y teóricos. Epsilon es para esta brecha. Si realmente hace muchos cálculos, es posible que termine con esta brecha siendo mayor que el épsilon estándar. Sea siempre extremadamente cuidadoso con los reales en las computadoras.

    – Jacques

    7 de junio de 2020 a las 13:02

En C++ es std::numeric_limits<double>::epsilon().

  • El archivo de encabezado es

    – Jive Dadson

    20 de julio de 2012 a las 2:48

  • De nada. Una cosa más a tener en cuenta es que no arroja una excepción si no hay épsilon. Simplemente devuelve cero en silencio. (Al menos en MSVC++ 2010) cout ::epsilon()

    – Jive Dadson

    23 de julio de 2012 a las 1:04


  • @JiveDadson épsilon para int No tiene sentido. ¿Supongo que es por eso que esperas una excepción?

    – wcochran

    20 de diciembre de 2018 a las 18:25


avatar de usuario
steve jesop

Debería estar en “float.h”. Eso es portátil, es parte de los estándares C y C++ (aunque en desuso en C++ – use <cfloat> o la respuesta de sbi para la compatibilidad con versiones anteriores “garantizada”).

Si no lo tiene, dado que sus dobles son IEEE de 64 bits, puede robar el valor del float.h de otra persona. Aquí está el primero que encontré:

http://opensource.apple.com/source/gcc/gcc-937.2/float.h

#define DBL_EPSILON 2.2204460492503131e-16

El valor me parece correcto, pero si quiere estar seguro de su compilador, puede verificar que (1.0 + DBL_EPSILON) != 1.0 && (1.0 + DBL_EPSILON/2) == 1.0

Editar: no estoy muy seguro de lo que quiere decir con “programáticamente”. Es una constante estándar, se supone que no debe calcularla, es una propiedad de la implementación que se le proporciona en un archivo de encabezado. Pero supongo que podrías hacer algo como esto. Nuevamente, asumiendo la representación IEEE o algo similar, de modo que DBL_EPSILON está obligado a ser cualquier potencia de 0.5 que represente un 1 en el último bit de precisión de la representación de 1.0:

double getDblEpsilon(void) {
    double d = 1;
    while (1.0 + d/2 != 1.0) {
        d = d/2;
    }
    return d;
}

Tenga en cuenta que, dependiendo de la configuración del compilador, los resultados intermedios pueden tener mayor precisión que doubleen cuyo caso obtendría un resultado más pequeño para d que DBL_EPSILON. Consulte el manual de su compilador o encuentre una manera de forzar el valor de 1.0 + d/2 para ser almacenado y recargado a un double objeto antes de compararlo con 1.0. En términos generales, en las PC depende de si su compilador usa las instrucciones FPU x86 (mayor precisión) o las operaciones de punto flotante x64 más nuevas (doble precisión).

  • ¿Cómo obtenerlo programáticamente?

    – vehomzzz

    14/10/2009 a las 13:30

  • Sospecho while ((double)(1.0 + d/2) != 1.0) { manejaría los “resultados intermedios podrían tener mayor precisión que double” tema.

    – chux – Reincorporar a Monica

    29 mayo 2019 a las 23:27

¿Ha sido útil esta solución?