Os números de ponto flutuante 99.15 e 28.85 e 78.30 não possuem representações binárias IEEE 754 exatas. Você pode ver isso com um programa em C que faz o mesmo cálculo:
#include <stdio.h>
int
main(int ac, char **av)
{
float a = 99.15;
float b = 20.85;
float c;
printf("a = %.7f\n", a);
printf("b = %.7f\n", b);
c = a - b;
printf("c = %.7f\n", c);
return 0;
}
Eu recebo essas respostas por um x86 e uma máquina x86_64 provavelmente porque ambos fazem IEEE 754 matemática de ponto flutuante:
a = 99.1500015 b = 20,8500004 c = 78,3000031
Veja o que acontece: números de ponto flutuante são representados com um bit de sinal (positivo ou negativo), um número de bits e um expoente. Nem todo número racional (que é o que um número "ponto flutuante" está neste contexto) pode ser representado exatamente no formato IEEE 754. Então, o hardware fica o mais próximo possível. Infelizmente, no seu caso de teste, o hardware não obtém uma representação exata de qualquer um dos 3 valores. Não será nem mesmo se você usar double
em vez de float
, o que awk
provavelmente faz.
Aqui está uma explicação adicional do espaçamento dos números de ponto flutuante que tem representações binárias exatas.
Provavelmente, você pode encontrar alguns valores que passam no teste e outros que não passam. Há muito mais que não.
Normalmente, as pessoas resolvem um problema de ponto flutuante fazendo algo assim:
if (abs(c) <= epsilon) {
// We'll call it equal
} else {
// Not equal
}
Isso é muito mais difícil de fazer em awk
. Se você está fazendo dinheiro com unidades monetárias e dois dígitos significativos de sub-unidade (dólares e centavos, digamos), você deve realizar todos os cálculos nas sub-unidades (centavos nos EUA). Não use ponto flutuante para fazer cálculos monetários. Você só vai se arrepender dessa decisão.