Risco de operações lógicas sobre as variáveis ​​de ponto flutuante em C ++

erros de arredondamento em ponto flutuante cálculo pode criar confusão com operações lógicas em C ++, então você deve ter cuidado realizar operações lógicas sobre as variáveis ​​de ponto flutuante. Considere o seguinte exemplo:

flutuar f1 = 10.0-float F2 = f1 / 3-bool b1 = (f1 == (F2 * 3.0)) - // são estes dois são iguais?

Mesmo que seja óbvio para nós que f1 é igual a f2 3 vezes, o valor resultante de b1 não é necessariamente verdade. A variável de ponto flutuante não pode conter um número ilimitado de algarismos significativos. Assim, f2 não é igual ao número que chamaríamos # 147 e três-e-um-terço, # 148- mas sim para 3,3333 # 133-, parando depois de algum número de casas decimais.

UMA flutuador variável suporta cerca de 7 dígitos de precisão, enquanto um duplo suporta uma skosh mais de 16 dígitos. Estes números são aproximados porque o computador é susceptível de gerar um número como 3.3333347 devido a caprichos em cálculos de ponto flutuante.

Agora, em matemática pura, o número de 3s após o ponto decimal é infinito, mas nenhum computador construído pode lidar com um número infinito de dígitos. Assim, depois de multiplicar 3,3333 por 3, você começa 9,9999 em vez dos 10 que você obteria se multiplicaram # 147 e três-e-um-terço # 148- - com efeito, uma erro de arredondamento. Tais pequenas diferenças podem ser imperceptível para uma pessoa, mas não para o computador. Igualdade significa exatamente isso - exato igualdade.

Os processadores modernos são sofisticados na execução de tais cálculos. O processador pode, de fato, acomodar o erro de arredondamento, mas de dentro C ++, você não pode prever exatamente o que qualquer processador irá fazer.

A comparação mais seguro se segue:

flutuar f1 = 10.0-float F2 = f1 / 3-float F3 = F2 * 3.0-float delta = F1 - F3-bool bEqual = -0,0001 lt; delta delta lt; 0.0001-

Esta comparação é verdade E se f1 e F3 fazem parte de uma pequena delta umas das outras, o que ainda deve ser verdade mesmo se você levar algum pequeno erro de arredondamento em conta.

A lógica AND e lógico OR || operadores em C ++ executar o que é chamado avaliação de curto-circuito. Considere o seguinte:

condition1 condition2

E se condition1 não é verdade, o resultado global não é verdade, não importa o que o valor de condition2. (Por exemplo, condition2 poderia ser verdade ou falso . Sem alterar o resultado) A mesma situação ocorre no seguinte:

condition1 || condition2

E se condition1 é verdade, o resultado é verdade, não importa o que o valor de condition2 é.

Para economizar tempo, C ++ não avalia condition2 Se ele não precisa. Por exemplo, na expressão condition1 condition2, C ++ não avaliar condition2 E se condition1 é falso. Da mesma forma, na expressão condition1 || condition2, C ++ não avaliar condition2 E se condition1 é verdade. Isto é conhecido como a avaliação de curto-circuito.

curto-circuito avaliação pode significar que condition2 não é avaliada mesmo se essa condição tem efeitos colaterais. Considere o seguinte trecho de código reconhecidamente inventado:

int nArg1 = 1-int nArg2 = 2-int nArg3 = 3-boleano b = (nArg1> nArg2) (NArg2 ++> nArg3) -

a variável nArg2 nunca é incrementado, porque o comparador nArg2 ++> nArg3 não é realizada. Não há necessidade, porque nArg1> nArg2 já voltou um falso Portanto, a expressão global deve ser falso.

menu