Diferença entre maneiras de comparar números de ponto flutuante

7

Parece haver muitas abordagens para julgar se dois números de ponto flutuante são idênticos. Aqui estão alguns exemplos que encontrei:

  1. fabs(x - y) < n * FLT_EPSILON * fabs(x) OU fabs(x - y) < n * FLT_EPSILON * fabs(y)

  2. fabs(x - y) < n * FLT_EPSILON * fabs(x + y)

  3. fabs(x - y) < n * FLT_EPSILON * fabs(x + y) || fabs(x - y) < FLT_MIN)

  4. fabs(x - y) < n * FLT_EPSILON * sqrt(x * x + y * y + FLT_EPSILON * FLT_EPSILON)

Estou realmente confuso sobre eles. Suponha que exista uma maneira melhor de comparar dois números de ponto flutuante, que é o mais simples e o mais preciso; as outras abordagens nem deveriam existir. Portanto, essas diferentes maneiras devem ter prós e contras próprios.

Minha pergunta é: Para fazer "cálculos reais", qual abordagem é a mais precisa ?


Links de referência:

http://accu.org/index.php/journals/1558 (1 e 4)

https://stackoverflow.com/a/10335601/5399734 (2 e 3)

nalzok
fonte
2
Infelizmente, a análise numérica não é trivial e a escolha correta pode depender do tipo de cálculo que você está fazendo.
Yuval Filmus 24/03

Respostas:

2

Você está legitimamente confuso, porque essas respostas misturam conceitos incompatíveis em uma confusão certa.

Se você quiser saber se dois números de ponto flutuante são iguais, use o operador "==", que informará absolutamente corretamente se eles são iguais.

Se você quiser saber se eles são idênticos, isso é um pouco mais complicado: existem +0 e -0 iguais, mas não idênticos, e NaNs (Não-um-Número) que não são iguais, nem iguais a si mesmos , mas pode ser idêntico.

Agora, se você executar aritmética de ponto flutuante, pode acontecer que dois cálculos que deveriam ter dado o mesmo resultado matemático produzam resultados diferentes devido a erros de arredondamento. Também pode acontecer que dois cálculos que deveriam ter dado resultados matemáticos diferentes produzam o mesmo resultado.

Não existe uma regra rápida e fácil . Você precisa pensar sobre qual é seu objetivo e como alcançá-lo. E todo caso é diferente.

PS. (4) é simplesmente horrível. Totalmente, totalmente errado. Se você usar precisão dupla e um de x, y for maior que 10 ^ 160, quase todos os dois números serão considerados "iguais" por este código.

PS. (1-3) são igualmente terríveis, porque afirmam que 0 ≠ 0.

PS. (3) é horrível - destrói completamente a idéia de fluxo insuficiente gradual.

PS. Como regra, você deve usar precisão dupla em vez de precisão única, a menos que tenha uma boa razão para não; uma razão que você pode explicar e defender.

gnasher729
fonte