[La «bonne réponse» passe sous silence la sélection K
. La sélection K
finit par être aussi ponctuelle que la sélection, VISIBLE_SHIFT
mais la sélection K
est moins évidente car, contrairement à VISIBLE_SHIFT
elle, elle n'est basée sur aucune propriété d'affichage. Choisissez donc votre poison - sélectionnez K
ou sélectionnez VISIBLE_SHIFT
. Cette réponse préconise la sélection VISIBLE_SHIFT
, puis démontre la difficulté de sélectionner K
]
Précisément en raison d'erreurs rondes, vous ne devez pas utiliser la comparaison des valeurs «exactes» pour les opérations logiques. Dans votre cas spécifique d'une position sur un affichage visuel, il peut ne pas avoir d'importance si la position est de 0,0 ou 0,000000000003 - la différence est invisible à l'œil. Donc, votre logique devrait être quelque chose comme:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
Cependant, à la fin, «invisible à l'œil» dépendra de vos propriétés d'affichage. Si vous pouvez limiter l'affichage (vous devriez pouvoir); puis choisissez VISIBLE_SHIFT
d'être une fraction de cette limite supérieure.
Maintenant, la «bonne réponse» repose sur K
nous allons donc explorer la sélection K
. La «bonne réponse» ci-dessus dit:
K est une constante que vous choisissez de telle sorte que l'erreur cumulée de vos calculs soit définitivement limitée par K unités en dernier lieu (et si vous n'êtes pas sûr d'avoir correctement calculé le lien d'erreur, augmentez K quelques fois plus que ce que vos calculs dire que ça devrait être)
Nous avons donc besoin K
. Si obtenir K
est plus difficile, moins intuitif que de sélectionner my, VISIBLE_SHIFT
vous déciderez de ce qui vous convient . Pour trouver, K
nous allons écrire un programme de test qui examine un tas de K
valeurs afin que nous puissions voir comment il se comporte. Doit être évident comment choisir K
, si la «bonne réponse» est utilisable. Non?
Nous allons utiliser, comme «bonne réponse» les détails:
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Essayons simplement toutes les valeurs 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, donc K devrait être 1e16 ou plus si je veux que 1e-13 soit «zéro».
Donc, je dirais que vous avez deux options:
- Faites un calcul epsilon simple en utilisant votre jugement d'ingénierie pour la valeur de 'epsilon', comme je l'ai suggéré. Si vous faites des graphiques et que «zéro» est censé être un «changement visible», examinez vos ressources visuelles (images, etc.) et jugez ce que peut être epsilon.
- N'essayez pas de calculs en virgule flottante avant d'avoir lu la référence de la réponse non-cargo-culte (et obtenu votre doctorat dans le processus), puis utilisez votre jugement non intuitif pour sélectionner
K
.
fabs(x+y)
est problématique six
ety
(peut) avoir un signe différent. Pourtant, une bonne réponse contre la vague de comparaisons fret-culte.