[La 'respuesta correcta' pasa por alto la selección K
. Seleccionar K
termina siendo tan ad-hoc como seleccionar, VISIBLE_SHIFT
pero seleccionar K
es menos obvio porque, a diferencia de VISIBLE_SHIFT
esto, no se basa en ninguna propiedad de visualización. Por lo tanto, elija su veneno: seleccione K
o seleccione VISIBLE_SHIFT
. Esta respuesta aboga por seleccionar VISIBLE_SHIFT
y 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_SHIFT
ser una fracción de ese límite superior.
Ahora, la "respuesta correcta" se basa K
así 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 K
es más difícil, menos intuitivo que seleccionar mi, VISIBLE_SHIFT
entonces usted decidirá qué funciona para usted. Para encontrarlo K
, vamos a escribir un programa de prueba que K
observe 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 six
yy
(puede) tener un signo diferente. Aún así, una buena respuesta contra la corriente de las comparaciones de culto de carga.