[La "risposta giusta" va oltre la selezione K. La selezione Kfinisce per essere ad-hoc come la selezione, VISIBLE_SHIFTma la selezione Kè meno ovvia perché a differenza di VISIBLE_SHIFTessa non è fondata su alcuna proprietà di visualizzazione. Scegli quindi il tuo veleno: seleziona Ko seleziona VISIBLE_SHIFT. Questa risposta sostiene la selezione VISIBLE_SHIFTe 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_SHIFTdi essere una frazione di quel limite superiore.
Ora, la "risposta giusta" si basa Kquindi 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_SHIFTallora deciderai cosa funziona per te. Per scoprire Kche stiamo per scrivere un programma di test che esamina un sacco di Kvalori 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 sexey(può) avere un segno diverso. Tuttavia, una buona risposta contro l'ondata di confronti tra culto e merci.