DEV Community

Cover image for Trabalhando com dinheiro!
Victor Osório
Victor Osório

Posted on

Trabalhando com dinheiro!

Ninguém nasce Sênior, se torna Sênior!

Se tornar um Sênior é um processo demorado, e requer muito suor. Como o mercado de computação tem se expandido exponencialmente, resolvi começar uma série de posts rápidos sobre tudo que um Sênior deve saber. Vamos ao primeiro....

Como lidar com dinheiro?

Quando vamos modelar um Objeto ou qualquer outro domínio, sempre imaginamos o tipo de dado antes mesmo de começar a escrever o dado.

Sabemos que nome é String, sobrenome é String, data de nascimento é um Date, data de ativação será um long, ou Timestamp. Podemos até, em algumas linguagens ter dúvida se usamos um Date ou Datetime. Mas tudo isso depende da linguagem escolhida, certo?

Errado!

Tudo depende da forma como o valor é armazenado em bytes. Sim! Você acha que existe um valor inteiro? Ou string? Não, existem bytes! Somente bytes! E esses valores são representados em bytes. Um inteiro por exemplo são 4 bytes alinhados. Assim um inteiro 0 é 00000000 00000000 00000000 00000000. Em Java um short 0 é 00000000 00000000. Fácil? Nem tanto...

Lembra dos conjuntos numéricos da matemática? Pois bem, números inteiros são fáceis, agora e os outros?

Quando eu preciso de um valor não exato, um float por exemplo? Sabe como é armazenado? Usando a notação floating point.

Então qualquer valores de dinheiro devem ser guardados em Float, certo?

Errado!

Vamos olhar bem de perto algumas operações do float ou double.

Alt Text

Entendeu porque 2.01 + 2.01 + 2.01 + 2.01 + 2.001 = 10.040999999999999? E não ‭10.041‬? 🙄🙄🙄

Float Point precision problem

Sim, esse é um erro bastante conhecido. Você pode pesquisar por ele na internet. Ele aparece quando são feitas várias operações com Floating Point.

Já vi ocorrer em sistemas em produção. Era um sistema de controle de estoque e compras. Havia várias ordem de compras, mas o valor vendido não batia com o caixa. Esse erro se deu em uma conta simple com 5 valores. Agora e se tivessemos 5.000 valores?

Vamos ver... E se somassemos 5.000 vezes 2.01? Deveria dar 10.050.

Alt Text

Opa! Tivemos um erro de 0,676! 😮😮😮😮😮

Solução em Java

Mas vamos com calma. Em Java esse problema foi resolvido com a criação da classe BigDecimal.

Nenhuma operação monetária deve ser feita com float ou decimal em hipotese alguma. Esse valores devem ser lidos como BigDecimal.

Alt Text

Fique Atento

  1. Se esse valor for instanciado com um double ou float irá herdar a imprecisão do valor original.
  2. Essa classe é imutável, então fique atento. Se você chamar os metodos, não irá alterar o valor da instância, apenas criar uma nova!

Alt Text

Conclusão

Guarde pra vida toda. Nunca armazene valores monetários em double ou float. Não importa a linguagem ou base de dados que você está usando.

Caso não saiba como resolver esse problema. Não se preocupe é normal. Amanhã vai surgir uma linguagem nova ou uma base de dados nova e 99,99999% dos desenvolvedores não sabaerão também. Pesquise no Google.

Oldest comments (0)