[La "risposta giusta" va oltre la selezione K
. La selezione K
finisce per essere ad-hoc come la selezione, VISIBLE_SHIFT
ma la selezione K
è meno ovvia perché a differenza di VISIBLE_SHIFT
essa non è fondata su alcuna proprietà di visualizzazione. Scegli quindi il tuo veleno: seleziona K
o seleziona VISIBLE_SHIFT
. Questa risposta sostiene la selezione VISIBLE_SHIFT
e quindi dimostra la difficoltà nella selezione K
]
Proprio a causa di errori rotondi, non è necessario utilizzare il confronto di valori "esatti" per le operazioni logiche. Nel tuo caso specifico di una posizione su un display visivo, non può importare se la posizione è 0,0 o 0,0000000003 - la differenza è invisibile all'occhio. Quindi la tua logica dovrebbe essere qualcosa del tipo:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
Tuttavia, alla fine, "invisibile alla vista" dipenderà dalle proprietà del display. Se puoi rilegare in alto il display (dovresti essere in grado di farlo); quindi scegli VISIBLE_SHIFT
di essere una frazione di quel limite superiore.
Ora, la "risposta giusta" si basa K
quindi esploriamo la raccolta K
. La "risposta giusta" sopra dice:
K è una costante che scegli in modo tale che l'errore accumulato dei tuoi calcoli sia delimitato definitivamente dalle unità K nell'ultimo posto (e se non sei sicuro di aver corretto il calcolo del limite di errore, rendi K alcune volte più grande di quello che calcoli dire che dovrebbe essere)
Quindi abbiamo bisogno K
. Se ottenere K
è più difficile, meno intuitivo di selezionare il mio, VISIBLE_SHIFT
allora deciderai cosa funziona per te. Per scoprire K
che stiamo per scrivere un programma di test che esamina un sacco di K
valori in modo da poter vedere come si comporta. Dovrebbe essere ovvio come scegliere K
, se la "risposta giusta" è utilizzabile. No?
Useremo, come i dettagli della "risposta giusta":
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Proviamo solo tutti i valori di 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, quindi K dovrebbe essere 1e16 o più grande se voglio che 1e-13 sia 'zero'.
Quindi, direi che hai due opzioni:
- Fai un semplice calcolo epsilon usando il tuo giudizio ingegneristico per il valore di "epsilon", come ho suggerito. Se stai facendo grafica e "zero" significa essere un "cambiamento visibile", allora esamina le tue risorse visive (immagini, ecc.) E giudica cosa può essere epsilon.
- Non tentare calcoli in virgola mobile fino a quando non hai letto il riferimento della risposta non-cargo-cult (e ottenuto il tuo dottorato di ricerca nel processo) e quindi usa il tuo giudizio non intuitivo per selezionare
K
.
fabs(x+y)
è problematico sex
ey
(può) avere un segno diverso. Tuttavia, una buona risposta contro l'ondata di confronti tra culto e merci.