DUVIDA ENTRE CDBL E CSNG

JCM0867 17/09/2017 22:26:20
#476628
Olá pessoal

Faço a soma de um valores de um grid
Resultado 135.852,79

Se faço:
Resultado = CDbl(Resultado).ToString([Ô]#,##0.00[Ô]) = 135.852,79 [txt-color=#e80000]-Valor Correto[/txt-color]
Resultado = CSng(Resultado).ToString([Ô]#,##0.00[Ô]) = 135.852,80
pq diferença de 1 centavo? Em outras situações dá até 3 centavos de diferença

Pode ser lixo na primeira soma? como retiro?

JABA 18/09/2017 00:35:19
#476630
Resposta escolhida
O [txt-color=#e80000]csng [/txt-color]arredonda conforme o valor do último número. Por exemplo, se o número for 135.852,74, vai arredondar para 135.852,7. Agora, se for 135.852,75, ele vai arredondar para 135.852,8. Ou seja, se o último número for maior ou igual a 5, ele arredonda o penúltimo número para cima, senão, o penúltimo número continua com o mesmo valor, e elimina o ultimo número em ambos os casos. Já o [txt-color=#e80000]Cdbl [/txt-color]não faz o arredondamento, deixando o número da mesma maneira que está.

FFCOUTO 18/09/2017 09:04:38
#476632
JCM0867,

Tanto o CSng quanto o CDbl tem problemas na questão de arredondamento pois são números de pontos flutuantes, veja aqui.

Para valores monetários eu recomendo o uso de Decimal (.NET) e Currency (VB6) pois ele trabalha de forma precisa nesta questão.

Bem, já tive uma experiência desagradável com essa questão em relatórios financeiros onde a diferença total podia chegar a R$ 100,00 devido ao volume de transações. Fica a dica.
JCM0867 18/09/2017 11:57:08
#476635
para valores monetários uso numeric(10,2) no banco e Single na declaração de variáveis numéricas quando é monetário e alguns percentuais
Passei em alguns lugares onde tem valores não parece ter dado problema com single. em que casos pode dar problemas? fiquei preocupado agora
No VB6 usava Double e tinha problemas com lixo nas casas decimais
GUIMORAES 18/09/2017 14:18:14
#476637
JCM0867,

Sempre usei Double nas declarações, mas sempre tomei cuidado com o arredondamento das casa.
Para o arredondamento, normalmente utilizo assim:
  
Double valor1 = Math.Round(135852.79, 2, MidpointRounding.AwayFromZero);
Double valor2 = Math.Round(135852.79, 2, MidpointRounding.ToEven);
JABA 18/09/2017 14:23:19
#476638
Citação:

Tanto o CSng quanto o CDbl tem problemas na questão de arredondamento pois são números de pontos flutuantes



Vou ter que discordar do colega FFCOUTO. Fiz os testes aqui e não houve o arredondamento. O que quero dizer por arredondamento não é pegar somente uma parte do número, e sim fazer com que o número anterior ao corte seja acrescido de uma unidade.

JCM0867 18/09/2017 22:52:57
#476646
Vou dar uma atenção quando ver que a segunda casa decimal com zero. foi o que vi em dois casos de arrendondamento
Deu a impressão que isso aconteceu quando executei um cálculo de soma em loop
do tipo [txt-color=#e80000]ValorTotal = ValorTotal + Mensalidade[/txt-color] diversas vezes, ou foi só coincidência?
GUIMORAES 19/09/2017 10:05:29
#476648
Citação:

:
Vou dar uma atenção quando ver que a segunda casa decimal com zero. foi o que vi em dois casos de arrendondamento
Deu a impressão que isso aconteceu quando executei um cálculo de soma em loop
do tipo [txt-color=#e80000]ValorTotal = ValorTotal + Mensalidade[/txt-color] diversas vezes, ou foi só coincidência?



Não existe coincidência na matemática, é provável que esteja acontecendo o arrendondamento e você não está percebendo.
Normalmente percebemos isto em valores mais altos, onde a diferença é aparente.

Formate seu código como mostrei abaixo, e verifique se o resultado é diferente
  
Double valor1 = Math.Round(135852.79, 2, MidpointRounding.AwayFromZero);
JABA 19/09/2017 13:00:40
#476652
é como eu tentei mostrar a ele, não tem mistério algum. Digamos que o número todo seja 135.852,795. Se ele arredondar com o csng, o resultado será 135.852,80. Por que? Porque ele sempre arredonda a última casa pra cima, independentemente do valor que esteja. Com o Cdbl, se o valor da última casa for maior ou igual a 5, ele é retirado e o número antes dele é acrescido de uma unidade. Se fosse 135.852,795, arredondaria para 135.852,80. Se fosse 135.852,794, arredondaria para 135.852,790.
FFCOUTO 19/09/2017 14:35:23
#476653
Amigos, percebo que não clicaram no link que disponibilizei para um melhor entendimento da questão do arredondamento e da forma como os pontos flutuantes trabalham na forma binária (que é o que o computador entende). Vejam aqui uma outra boa discussão do assunto (em inglês) http://www.xtremevbtalk.com/archive/index.php/t-219163.html.

Para valores pequenos, é quase certo não haver diferença. Mas quando os valores começam a subir, como relatado pelo colega JCM0867, a diferença pode ser tornar muito grande. Ainda mais quando lidamos com a área financeira, onde é necessário uma precisão de 100%.

Como falei, já passei por uma experiência ruim.

Ao colega JABA, fique à vontade para discordar. Estamos aqui para trocar experiências e ajudar uns aos outros. Desde que mantenhamos o bom nível da conversa acho extremamente válido a opinião de todos.

Ao JCM0867, minha sugestão para você é que no banco os campos monetários tenha uma precisão de 4 casas decimais. O tipo ideal seria o [ô]money[ô] (SQL Server), no caso de não possui-lo, use o numeric(18,4) e nas variáveis no software use o tipo decimal.

JABA 19/09/2017 16:47:58
#476655
Citação:

Amigos, percebo que não clicaram no link que disponibilizei para um melhor entendimento da questão do arredondamento e da forma como os pontos flutuantes trabalham na forma binária (que é o que o computador entende).



Eu cheguei dar uma lida, inclusive, já estudei isso na faculdade. Números irracionais são infinitos, e como a memória do PC é algo finito, o valor será quebrado em alguma parte. Só que o problema aqui não é a origem do número, e sim arredondar sobre um número já existente. Ou seja, a máquina gera um número quebrado por falta de recursos, e queremos arredonda-lo manualmente para um outro formato.

Citação:

Ao colega JABA, fique à vontade para discordar. Estamos aqui para trocar experiências e ajudar uns aos outros. Desde que mantenhamos o bom nível da conversa acho extremamente válido a opinião de todos.



Nós estamos respondendo à questão dele sobre ópticas diferentes . Você está respondendo com base nas consequências, e eu sobre o porquê de faltar o 1 centavo, pois esse foi o motivo da criação do tópico. Olha o que ele disse: [Ô]pq diferença de 1 centavo? Em outras situações dá até 3 centavos de diferença[Ô].
Página 1 de 2 [12 registro(s)]
Tópico encerrado , respostas não são mais permitidas