[A 'resposta correta' encobre a seleção K
. A seleção K
acaba sendo tão ad-hoc quanto a seleção, VISIBLE_SHIFT
mas a seleção K
é menos óbvia, porque, ao contrário VISIBLE_SHIFT
, não se baseia em nenhuma propriedade de exibição. Assim, escolha seu veneno - selecione K
ou selecione VISIBLE_SHIFT
. Esta resposta defende a seleção VISIBLE_SHIFT
e, em seguida, demonstra a dificuldade em selecionar K
]
Precisamente devido a erros de arredondamento, você não deve usar a comparação de valores 'exatos' para operações lógicas. No seu caso específico de uma posição em uma exibição visual, não importa se a posição é 0,0 ou 0,0000000003 - a diferença é invisível aos olhos. Portanto, sua lógica deve ser algo como:
#define VISIBLE_SHIFT 0.0001 // for example
if (fabs(theView.frame.origin.x) < VISIBLE_SHIFT) { /* ... */ }
No entanto, no final, 'invisível aos olhos' dependerá das propriedades da sua exibição. Se você pode limitar o display (você deve conseguir); escolha VISIBLE_SHIFT
ser uma fração desse limite superior.
Agora, a 'resposta certa' se baseia, K
então vamos explorar a escolha K
. A 'resposta correta' acima diz:
K é uma constante que você escolhe para que o erro acumulado de seus cálculos seja definitivamente limitado por K unidades em último lugar (e se você não tiver certeza de ter acertado o cálculo de erro, faça K algumas vezes maior do que seus cálculos diga que deveria ser)
Então nós precisamos K
. Se conseguir K
é mais difícil, menos intuitivo do que selecionar o meu, VISIBLE_SHIFT
então você decidirá o que funciona para você. Para descobrir K
, vamos escrever um programa de teste que analise vários K
valores para que possamos ver como ele se comporta. Deveria ser óbvio como escolher K
, se a 'resposta certa' for utilizável. Não?
Vamos usar como detalhes da 'resposta certa':
if (fabs(x-y) < K * DBL_EPSILON * fabs(x+y) || fabs(x-y) < DBL_MIN)
Vamos apenas tentar todos os 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, então K deve ser 1e16 ou maior se eu quiser que 1e-13 seja 'zero'.
Então, eu diria que você tem duas opções:
- Faça um cálculo epsilon simples usando seu julgamento de engenharia pelo valor de 'epsilon', como sugeri. Se você estiver criando gráficos e 'zero' for uma 'mudança visível', examine seus recursos visuais (imagens, etc.) e julgue o que é epsilon.
- Não tente fazer cálculos de ponto flutuante até ler a referência da resposta que não é de carga (e obter seu doutorado no processo) e, em seguida, use seu julgamento não intuitivo para selecionar
K
.
fabs(x+y)
é problemático sex
ey
(pode) ter sinal diferente. Ainda assim, uma boa resposta contra a maré de comparações entre cultos de carga.