BaDcereal 4 Denunciar post Postado Janeiro 21, 2010 PHP/MySQL - Trabalhando com Valores Monetários com precisão em casas decimais. Esses dias me deparei com um problema no trabalho, estava desenvolvendo um sistema de administração interno para empresa onde envolvia cálculos monetários. O problema ocorreu quando tentei gravar no banco um numero com mais de 8 dígitos e 2 casas decimais de precisão. Primeiramente tentei usar o tipo de dados DOUBLE mas ele truncava as casas decimais. Exp.: eu inseria no banco 3.456.234.678,98 e na consulta ele me trazia 3.456.234.679,00 Moral da historia, ele estava truncando as casas decimais. Testei com o tipo FLOAT e obtive os mesmos resultados do tipo DOUBLE. Então depois de pesquisar na internet e nada encontrar que solucionasse meu problema, resolvi ler o manual do MySQL e encontrei o seguinte: "Os tipos de dados FLOAT e DOUBLE são usados para representar aproximadamente dados de valores numéricos." Mais adiante no manual encontrei o tipo DECIMAL que dizia: "Os tipos de dados DECIMAL e NUMERIC são usados para armazenar dados de valores numéricos com precisão. Eles são usados por valores para os quais é importante preservar a exatidão como, por exemplo, dados monetários."Esse era o cara que eu estava procurando ;) Sem mais delongas vamos ao que interessa a implementação. Não vou entrar em muitos detalhes quem estiver interessado em saber mais sobre os tipos de dados que o MySQL suporta pode consultar o manual nos links abaixo: Manual de Referência do MySQL 4.1 / 6.2.1. Tipos Numéricos – em português http://dev.mysql.com...1/pt/index.html MySQL 5.5 Reference Manual / 10.2. Numeric Types – em inglês http://dev.mysql.com...5/en/index.html Implementação: MySQL No MySQL configure sua tabela para receber o tipo de dado DECIMAL. DECIMAL(M,D) onde M é o numero de dígitos e D o numero de casas decimais. Exp.: salário DECIMAL(5,2) ele ira suportar a faixa numérica de -999.99 to 999.99 Se não for especificado nada entre parênteses ele assume o valor padrão M é 10. Ok depois de configurado o MySQL devidamente vamos ao PHP. PHP Primeiramente devemos remover a virgula e substituir ela por ponto porque o MySQL usa o padrão americano para gravar os dados. Escrevi uma pequena função para fazer isso: function moeda($get_valor) { $source = array('.', ','); $replace = array('', '.'); $valor = str_replace($source, $replace, $get_valor); //remove os pontos e substitui a virgula pelo ponto return $valor; //retorna o valor formatado para gravar no banco } //Chamada da função $valor_final=moeda($_POST['valor']); Ok tudo gravado no banco muito bonito, mas agora quando você fizer um SELECT ele não ira trazer o valor com deve. Para isso precisamos usar a função do PHP number_format() Abaixo a solução: $valor_servico = ' R$ ' . number_format($l['valor_servico'], 2, ',', '.'); O que exatamente faz essa linha? number_format pega o valor da variável $l que foi buscada no banco, separa as ultimas 2 casas a direita com uma virgula depois a cada 3 casa ele coloca um ponto a seguir concatena co valor com R$ para ficar bonitinho e armazena o resultado na variável $valor_servico Pronto, não entrei em muitos detalhes mas acho que consegui passar o conceito para vocês. Até a próxima. Compartilhar este post Link para o post Compartilhar em outros sites
Cazzeri 1 Denunciar post Postado Agosto 15, 2014 Muito bom :D Compartilhar este post Link para o post Compartilhar em outros sites
DJ Panik 1 Denunciar post Postado Março 4, 2016 function convertCoin($xCoin = "EN", $xDecimal = 2, $xValue) { $xValue = preg_replace( '/[^0-9]/', '', $xValue); // Deixa apenas números $xNewValue = substr($xValue, 0, -$xDecimal); // Separando número para adição do ponto separador de decimais $xNewValue = ($xDecimal > 0) ? $xNewValue.".".substr($xValue, strlen($xNewValue), strlen($xValue)) : $xValue; return $xCoin == "EN" ? number_format($xNewValue, $xDecimal, '.', '') : ($xCoin == "BR" ? number_format($xNewValue, $xDecimal, ',', '.') : NULL); } $xValue = "12345678"; // Podendo ser "R$ 123.456,78" ou somente "123.456,78" ou "123456,78" ou "123.45678" convertCoin("EN",0,$xValue); // 12345678 convertCoin("EN",1,$xValue); // 1234567.8 convertCoin("EN",2,$xValue); // 123456.78 convertCoin("EN",3,$xValue); // 12345.678 convertCoin("BR",0,$xValue); // 12.345.678 convertCoin("BR",1,$xValue); // 11.234.567,8 convertCoin("BR",2,$xValue); // 123.456,78 convertCoin("BR",3,$xValue); // 12.345,678 Fiz uma função pra melhorar a conversão de mão dupla. Convertendo antes de enviar pro banco, e depois de pegar do banco. Tenho quase toda certeza que ela pode ser melhorada pela galera que tem mais conhecimento... Mas já ta sendo bem satisfatório pra mim o resultado da mesma. Espero ter ajudado! Compartilhar este post Link para o post Compartilhar em outros sites