Quando normalmente faz sentido na programação testar a igualdade de dois números de ponto flutuante?
ie
a == b
onde tanto a & b são carros alegóricos.
Minha impressão ingênua é que sempre se testaria a diferença em relação a alguma tolerância epsilon.
Estou errado? O teste da igualdade de carros alegóricos pode ser significativo em certos contextos?
Algum exemplo da natureza? ou seja, de bases de código reais ou aplicativos disponíveis no git etc.
PS. Estou implícito assumindo que o uso do operador de igualdade em carros alegóricos é realmente significativo em alguns contextos; caso contrário, por que a maioria das linguagens de programação o permitiria.
floating-point
curious_cat
fonte
fonte
Respostas:
Uma implementação não ingênua dessa idéia provavelmente deve tirar vantagem do operador de comparação de igualdade para lidar com os casos especiais importantes que o padrão IEEE 754 contempla (infinitos, números desnormalizados ...).
Dê uma olhada em Como devo fazer a comparação de ponto flutuante? :
Às vezes, há realmente uma resposta correta e você deseja a igualdade exata. Testar a correção de uma implementação é um bom exemplo (ou seja, existem apenas quatro bilhões de carros alegóricos - portanto, teste todos! ).
fonte
Um exemplo óbvio onde
==
está ok é quandoa
eb
é o mesmo númeroa=c; b=c
, por exemplo, para verificar sea
eb
foi inicializado da mesma maneira. Claro,|a-b| < epsilon
também funcionaria aqui. O único problema é, quão pequeno éepsilon
?Além disso,
a == b
seria compilado em uma instrução enquanto|a-b| < epsilon
levaria algumas.fonte
for x in [0..n] step w: for y in [0..n] step w: add_tile(x, y)
. Nesse caso,t1.x == t2.x
é uma maneira perfeitamente segura de testar se os dois blocos estão em um plano. Você só precisa|a-b|<epsilon
quandoa
eb
são resultados de cálculos diferentes que deveriam obter o mesmo valor. Mas muitas vezes você tem o resultado de um cálculo armazenado em duas variáveis ou sobrescreve variáveis com constantes.Um exemplo extremo: a IBM foi a primeira empresa a construir processadores com uma instrução de adição múltipla combinada. Usando essa instrução, eles criaram um método muito rápido para calcular raízes quadradas de acordo com o padrão IEEE-754. Este método falha para um único valor de entrada 1 ≤ x <4: Se x for o maior número representável como um número de ponto flutuante menor que 4, o resultado será arredondado incorretamente.
Então, em algum lugar de sua implementação, eles verificam se x é igual a um valor específico. Eles querem reconhecer esse valor, e não outros.
fonte
Não há receitas únicas. Em este artigo não é um tratamento exaustivo, onde pode ser encontrada uma resposta completa com técnica e código.
Em resumo, existem principalmente três casos:
Sua ideia de usar uma comparação contra uma tolerância é boa para alguns casos, mas também há uma técnica baseada na Unidade em último lugar ( ULP ), descrita dentro do artigo
Como acima, há situações em que você pode usá-lo, mas seja avisado. Por exemplo, o compilador gcc possui um aviso:
Atualizar
Acrescento algumas considerações acima desse argumento e elas não estão estritamente relacionadas ao caso
a == b
.Igualdade com expressão
Considerando o caso:
a b c
Portanto, neste caso, o uso de
==
é mais delicado.Portando em ambientes diferentes
Quando portamos um código em ambientes diferentes (máquina diferente), podemos obter resultados diferentes (por exemplo, tente pensar em teste de unidade). Também no caso, o uso de
==
é delicado.fonte
Sua "impressão ingênua" não é uma "impressão ingênua" - é o resultado de ler sobre aritmética de ponto flutuante e entender apenas metade disso. A "impressão ingênua" seria a impressão óbvia de que, para descobrir se a e b são iguais, você pergunta se são iguais.
Há muitas situações em que tudo que você precisa saber é se dois números de ponto flutuante são iguais ou não. Existem muitas situações em que você sabe que não há erros de arredondamento ou variações devido a erros de arredondamento. Como converter números decimais em ponto flutuante, que serão determinísticos em qualquer implementação sã.
Aqui está uma boa: alguém afirmou que, para quaisquer dois números de ponto flutuante a, b, o resultado de (b + a + b) e (b + b + a) são os mesmos e você deseja testar essa afirmação. Tente fazer isso sem comparar dois números de ponto flutuante para igualdade.
Aqui está um exemplo melhor: tente criar um conjunto de números de ponto flutuante.
fonte
Consulte esta pergunta: /cs/19013/is-transitivity-required-for-a-sorting-algorithm?rq=1
Explica muito bem como a comparação de ponto flutuante com algum epsilon pode levar a uma falha completa e total do algoritmo quicksort.
fonte