Ads 468x60px

quinta-feira, 9 de maio de 2013

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!

Nenhum comentário:

Postar um comentário