Pregunta

Para hacer que el problema a corto Digamos que quiero para calcular la expresión de a / (b - c) floats.

Para asegurarse de que el resultado es significativo, puedo comprobar si b y c están en iguales:

float EPS = std::numeric_limits<float>::epsilon();
if ((b - c) > EPS || (c - b) > EPS)
{
    return a / (b - c);
}

pero mis pruebas muestran que no es suficiente para garantizar que hayan dado resultados significativos ni no no proporcionar un resultado si es posible.

Caso 1:

a = 1.0f;
b = 0.00000003f;
c = 0.00000002f;

Resultado:. El Si no se cumple la condición, pero la expresión produciría un resultado correcto 100000008 (en cuanto a la precisión de los flotadores)

Caso 2:

a = 1e33f;
b = 0.000003;
c = 0.000002;

Resultado:. se cumple la condición si, pero la expresión no produce un resultado significativo +1.#INF00

Me pareció mucho más fiable para comprobar el resultado, no los argumentos:

const float INF = numeric_limits<float>::infinity();
float x = a / (b - c);
if (-INF < x && x < INF)
{
     return x;
}

Pero para qué es la épsilon continuación, y por qué todo el mundo está diciendo épsilon es bueno usar?

¿Fue útil?

Solución

"debe utilizar un épsilon cuando se trata de un flotante" es una reacción automática de los programadores con una comprensión superficial de cálculos de punto flotante, para las comparaciones en general (no sólo a cero).

Esto es generalmente inútil porque no le dice cómo reducir al mínimo la propagación de errores de redondeo, que no le dice cómo evitar problemas de cancelación o de absorción, e incluso cuando su problema de hecho está relacionado con la comparación de dos flotadores, lo que no indicará qué valor de épsilon es justo para lo que está haciendo .

Si usted no ha leído Lo que todo informático debe saber Acerca de aritmética de punto flotante , es un buen punto de partida. Además de eso, si usted está interesado en la precisión del resultado de la división en su ejemplo, usted tiene que estimar la b-c imprecisa fue hecho por anterior errores de redondeo, porque de hecho si b-c es pequeño, una pequeño error absoluto corresponde a un gran error absoluto en el resultado. Si su preocupación es sólo que la división no se debe volcar, entonces la prueba (en el resultado) es correcto. No hay ninguna razón a prueba para un divisor nula con números de punto flotante, que acaba de probar para el desbordamiento del resultado, que conjugue los casos en que el divisor es nula y en el que el divisor es tan pequeño como para que el resultado no representable con alguna precisión.

En cuanto a la propagación de errores de redondeo, existe analizadores especializados que pueden ayudar a estimar que, debido a que es algo tedioso de hacer a mano.

Otros consejos

Epsilon se utiliza para determinar si dos números de sujetos a error de redondeo son lo suficientemente cerca para ser considerado "iguales". Tenga en cuenta que es mejor fabs(b/c - 1) < EPS prueba de fabs(b-c) < EPS, e incluso mejor - gracias al diseño del IEEE flota - abs(*(int*)&b - *(int*)&c) < EPSI a prueba (donde EPSI es un pequeño número entero)

.

Su problema es de una naturaleza diferente, y probablemente garantiza prueba el resultado en lugar de las entradas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top