[La 'respuesta correcta' pasa por alto la selección K. Seleccionar Ktermina siendo tan ad-hoc como seleccionar, VISIBLE_SHIFTpero seleccionar Kes menos obvio porque, a diferencia de VISIBLE_SHIFTesto, no se basa en ninguna propiedad de visualización. Por lo tanto, elija su veneno: seleccione Ko seleccione VISIBLE_SHIFT. Esta respuesta aboga por seleccionar VISIBLE_SHIFTy luego demuestra la dificultad de seleccionar K]
Precisamente debido a errores redondos, no debe usar la comparación de valores 'exactos' para operaciones lógicas. En su caso específico de una posición en una pantalla visual, no puede importar si la posición es 0.0 o 0.0000000003; la diferencia es invisible para el ojo. Entonces su lógica debería ser algo como:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
Sin embargo, al final, 'invisible a la vista' dependerá de las propiedades de su pantalla. Si puede hacer un límite superior de la pantalla (debería poder hacerlo); luego elige VISIBLE_SHIFTser una fracción de ese límite superior.
Ahora, la "respuesta correcta" se basa Kasí que exploremos la selección K. La 'respuesta correcta' anterior dice:
K es una constante que elige de tal manera que el error acumulado de sus cálculos está definitivamente limitado por K unidades en último lugar (y si no está seguro de haber acertado el cálculo del límite de error, haga que K sea un poco más grande de lo que sus cálculos decir que debería ser)
Entonces lo necesitamos K. Si obtener Kes más difícil, menos intuitivo que seleccionar mi, VISIBLE_SHIFTentonces usted decidirá qué funciona para usted. Para encontrarlo K, vamos a escribir un programa de prueba que Kobserve un conjunto de valores para que podamos ver cómo se comporta. Debería ser obvio cómo elegir K, si la "respuesta correcta" es utilizable. ¿No?
Vamos a utilizar, como los detalles de 'respuesta correcta':
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Probemos con todos los valores de K:
#include <math.h>
#include <float.h>
#include <stdio.h>
void main (void)
{
double x = 1e-13;
double y = 0.0;
double K = 1e22;
int i = 0;
for (; i < 32; i++, K = K/10.0)
{
printf ("K:%40.16lf -> ", K);
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
printf ("YES\n");
else
printf ("NO\n");
}
}
ebg@ebg$ gcc -o test test.c
ebg@ebg$ ./test
K:10000000000000000000000.0000000000000000 -> YES
K: 1000000000000000000000.0000000000000000 -> YES
K: 100000000000000000000.0000000000000000 -> YES
K: 10000000000000000000.0000000000000000 -> YES
K: 1000000000000000000.0000000000000000 -> YES
K: 100000000000000000.0000000000000000 -> YES
K: 10000000000000000.0000000000000000 -> YES
K: 1000000000000000.0000000000000000 -> NO
K: 100000000000000.0000000000000000 -> NO
K: 10000000000000.0000000000000000 -> NO
K: 1000000000000.0000000000000000 -> NO
K: 100000000000.0000000000000000 -> NO
K: 10000000000.0000000000000000 -> NO
K: 1000000000.0000000000000000 -> NO
K: 100000000.0000000000000000 -> NO
K: 10000000.0000000000000000 -> NO
K: 1000000.0000000000000000 -> NO
K: 100000.0000000000000000 -> NO
K: 10000.0000000000000000 -> NO
K: 1000.0000000000000000 -> NO
K: 100.0000000000000000 -> NO
K: 10.0000000000000000 -> NO
K: 1.0000000000000000 -> NO
K: 0.1000000000000000 -> NO
K: 0.0100000000000000 -> NO
K: 0.0010000000000000 -> NO
K: 0.0001000000000000 -> NO
K: 0.0000100000000000 -> NO
K: 0.0000010000000000 -> NO
K: 0.0000001000000000 -> NO
K: 0.0000000100000000 -> NO
K: 0.0000000010000000 -> NO
Ah, entonces K debería ser 1e16 o mayor si quiero que 1e-13 sea 'cero'.
Entonces, diría que tienes dos opciones:
- Haga un cálculo simple de epsilon utilizando su criterio de ingeniería para el valor de 'epsilon', como he sugerido. Si está haciendo gráficos y 'cero' está destinado a ser un 'cambio visible' que examine sus activos visuales (imágenes, etc.) y juzgue qué puede ser épsilon.
- No intente ningún cálculo de coma flotante hasta que haya leído la referencia de la respuesta que no es de culto de carga (y haya obtenido su doctorado en el proceso) y luego use su juicio no intuitivo para seleccionar
K.
fabs(x+y)es problemático sixyy(puede) tener un signo diferente. Aún así, una buena respuesta contra la corriente de las comparaciones de culto de carga.