Tutorial.: Erro em operações com números reais em JavaScript
O que fazer quando 0,1 + 0,2 não é igual à 0,3? Na realidade, a soma de 0,1 + 0,2 resultaria em algo próximo de 0,30000000000000004. Saiba como isso funciona e como contornar esse mistério complicado de se deduzir no JavaScript...
Diferentemente do que se possa pensar, isso não é um bug da linguagem. Na verdade, os números reais no JavaScript são números de ponto flutuante binários. Na nossa cabeça, quando falamos em números reais, pensamos:
| Parte inteira | Separador (vírgula ou ponto) | Parte fracionária |
Para nós, é muito mais fácil compreender desta forma, mas para o computador isto custa processamento e armazenamento e, para evitar esse custo, a utilização de ponto flutuante foi adotada e a norma que a define é a IEEE 754-2008. Seria representada como:
| Sinal | Expoente | Mantissa |
Isto é, em 32bits (precisão simples),
1 bit para o sinal
8 bits para o expoente
23 para a mantissa
Ou em 64bits (precisão dupla),
1 bit para o sinal
11 bits para o expoente
52 para a mantissa
Sendo assim, aquele número pequeno com o qual já estamos acostumados, na verdade, vai se tornar um monstrinho composto por 0s e 1s multiplicados por uma base e elevado à um expoente. Curioso, não?
Bem, este tutorial não tem a intenção de ensinar a conversão (isso é feito nos 2 primeiros semestres de uma faculdade de TI que se preze), mas sim dar a dica de como contornar isso em um código JavaScript.
Vamos dar um exemplo bem infeliz para quem lida com estacionamentos de Shoppings.
Digamos que você vá à um determinado Shopping em Brasília para dar uma volta e acaba comprando um picolé porque estava calor. Agora, por algum motivo louco, você quer somar o que gastou utilizando JavaScript. O picolé custou uns R$ 3,10, mas a cara-de-pau da empresa do estacionamento te cobrou R$ 7,20 pelo tempinho que você ficou passeando. Vamos somar:
var picole = 3.10;
var estacionamento = 7.20;
var total = picole + estacionamento;
console.log(total);
//Resultará na saída: 10.299999999999999
WTF?! Cadê meu 1 trilhonésimo de centavo? Vou cobrar...
Bem, na verdade já sabemos que isso foi causado pela notação em ponto flutuante. Agora imagine isso em um código muito maior e que some diversas coisas... Em se tratando de dinheiro, basicamente utilizamos apenas duas (2) casas decimais (esqueça os postos de gasolina com seus valores ridículos de R$ 2,989 pra dizer que tá mais barato que o outro posto que custa R$ 2,99), então multiplicamos os valores por 100 para remover esta parte decimal, somamos e depois dividimos por 100 novamente:
var picole = 3.10;
var estacionamento = 7.20;
picole = picole * 100;
estacionamento = estacionamento * 100;
var total = picole + estacionamento;
total = total / 100;
console.log(total);
//Resultará na saída: 10.3
Resolvido!
Estacionamento caro do c@#$%&*... Dava pra comprar mais dois picolés...
E por hoje é só, pessoal!
Esperamos que este tutorial tenha sido proveitoso para vocês
Mandem suas dúvidas e sugestões para que possamos compartilhar com a nossa comunidade.
Gostou do tutorial? Ele te ajudou? Então clique nos botões "Curtir" e "+1", e compartilhe esta publicação no Facebook ou Google+, pode ser que outras pessoas também a achem útil! =D
Fiquem atentos para mais dicas e tutoriais aqui mesmo no Reduto Nerd!
No comments