Arredondamento de Valor. Onde?
13/05/2008
0
ValorIncompleto := QtdeParcelas * DuasCasasDecimais(DMEntradaNota.CdsEntradaNota.FieldByName(´VALORNOTA´).AsFloat / QtdeParcelas);
Resto := DMEntradaNota.CdsEntradaNota.FieldByName(´VALORNOTA´).AsFloat - ValorIncompleto;
Este código é responsável por ´acertar´ o valor total de uma certa nota pois,
sem este código, o delphi fazia o arredondamento, e quando por exemplo
o valor da nota era de R$ 1,00 e este valor fosse dividido em 3 parcelas,
aparecia para o usuário 3 parcelas de R$ 0,33.
Logo, total das parcelas ficava, R$ 0,99.
{ Não preciso falar da importância de R$ 0,01 num fechamento de caixa por exemplo... }
este código estava fluindo bem, fazendo a somatório do resto na última parcela, até que eu inseri para teste, os seguintes valores:
VALORNOTA: R$ 9,78
QTDEPARCELAS: 3
Não entendi o porque, ou onde está havendo o arredondamento, mas com estes valores o delphi retorna o seguinte resultado:
1ª Parcela: 3,26
2ª Parcela: 3,26
3ª Parcela: 3,29
Com os testes descobri que o delphi faz a seguinte conta e com o seguinte resultado:
9,78 / 3 = 3,25 {Os valores são exatos como estes mesmo}
Logo, 3 * 3,25 = R$ 9,75
Logo, R$ 9,78 - R$ 9,75 = R$ 0,03 <---- RESTO
Nisso, ele soma esses R$ 0,03 na ultima parcela, totalizando o valor da nota como R$ 9,81
A FIM DE ESCLARECIMENTO: função DuasCasasDecimais:
function DuasCasasDecimais(valor : real) : real;
begin
result := Trunc(Valor * 100) / 100;
end;
Se alguém poder me ajudar, por favor.
agradeço.
Rb2228
Posts
13/05/2008
Marco Salles
entre as duas funçoes abaixo..
function DuasCasasDecimaisExtended(valor :extended) : extended; begin result := Trunc(Valor * 100) / 100; end;
showmessage(floattostr(DuasCasasDecimais(9.78))); showmessage(floattostr(DuasCasasDecimaisExtended(9.78)));
como se trata de arredondamento usar Extended pode fornecer resultados mais precisos...
14/05/2008
Webjoel
Você não precisa usar esta função que você criou, o delphi já tem uma própria.
Ex:
valorParcela := RoundTo(VALOR,-2); //neste caso vai arredondar para duas casas decimais, mas você pode trocar o "-2" por outro número dependndo do arredondamento desejado.
14/05/2008
Rb2228
alterei a função e utilizei o extended, e alterei as variáveis ValorIncompleto e Resto tbm. Não funcionou.
Simplificando: Tenho o valor total da nota, o usuário insere a qtde de parcelas. Tenho uma rotina que divide o valor total em parcelas e mostro as parcelas, cada qual com o seu respectivo valor num grid.
O problema é que no grid, é mostrado apenas duas casas após a vírgula, e eu calculo a soma das parcelas para comparar com o valor total da nota.
Como no grid é mostrado apenas duas casas após a virgula, o que de fato nao esta incorreto pois se trata de dinheiro, imagine os seguintes valores:
Valor total da nota: R$ 100,00 Qtde Parcelas: 3
Valores no grid:
1ª Parcela: 33,33
2ª Parcela: 33,33
3ª Parcela: 33,33
Total: 99,99 <------- Ficou faltando R$ 0,01 para chegar no R$ 100,00.
Então tenho a rotina postada no topico para me retornar o valor que falta para completar, e somo esse valor na ultima parcela, assim:
1ª Parcela: 33,33
2ª Parcela: 33,33
3ª Parcela: 33,34
Total: 100,00 <------- Valor correto.
PROBLEMA: Com estes valores: Valor Nota: R$ 9,78 Qtde Parcelas: 3
não da certo pois o delphi insiste em que 9,78 / 3 resulta em 3,25.
e mostra os seguintes valores:
1ª Parcela: 3,26
2ª Parcela: 3,26
3ª Parcela: 3,29
Total: 9,81 <------- Ficou sobrando R$ 0,03
simplifiquei ou confundi mais ainda?
obrigado.
14/05/2008
Rb2228
14/05/2008
Edilcimar
Ex: ValorTotal := 100, Parcela1 = 100/3, Parcela2 = 100/3 e Parcela3 = ValorTotal - Parcela1 - Parcela2
14/05/2008
Marco Salles
function DuasCasasDecimaisExtended(valor :extended) : extended; begin result := Trunc(Valor * 100) / 100; end;
procedure TForm1.Button1Click(Sender: TObject); var t,r,s:extended; i,n:integer; begin t:=strtofloat(edit1.text); n:=strtoint(edit2.text); s:=0; r:=DuasCasasDecimaisExtended(t/n); for i:=1 to n-1 do begin cds.Append; cds.FieldByName(´valorEmReal´).AsFloat:=r; cds.FieldByName(´ValorEmCurrency´).AsFloat:=r; cds.Post; s:=s+r; end; s:=t-s; cds.Append; cds.FieldByName(´r´).AsFloat:=s; cds.FieldByName(´c´).AsFloat:=s; cds.FieldByName(´e´).AsFloat:=s; cds.Post; end;
Se Deu certo comigo provavelmente vai dar certo com voce...
14/05/2008
Rb2228
não sei se concorda, mas o Edilcimar tem razão. uma forma mais simplificada de se fazer.
mas o problema ainda persiste pois, o delphi não esta fazendo os cálculos corretamente.
estou com o seguinte codigo agora:
If (i = QtdeParcelas) Then DMEntradaNota.CdsPagamentoNota.FieldByName(´CDPNVALORPARCELA´).AsFloat := DMEntradaNota.CdsEntradaNota.FieldByName(´CDENVALORNOTA´).AsFloat - (QtdeParcelas - 1) * (DuasCasasDecimais(DMEntradaNota.CdsEntradaNota.FieldByName(´CDENVALORNOTA´).AsFloat / QtdeParcelas)) Else DMEntradaNota.CdsPagamentoNota.FieldByName(´CDPNVALORPARCELA´).AsFloat := DMEntradaNota.CdsEntradaNota.FieldByName(´CDENVALORNOTA´).AsFloat / QtdeParcelas;
com os mesmos valores o erro ainda persiste. :? [/code]
14/05/2008
Marco Salles
edicilmar escreveu:
Mas foi [b:55dd9ecb13]exatamente[/b:55dd9ecb13] o que lhe apresentei no ultimo post , com o exemplo do clientDataSet
function DuasCasasDecimaisExtended(valor :extended) : extended; begin result := Trunc(Valor * 100) / 100; end;
procedure TForm1.Button1Click(Sender: TObject); var ValorTotal,parcela,Soma:extended; i,n:integer; begin ValorTotal:=strtofloat(edit1.text); n:=strtoint(edit2.text); //Numerod e parcelas Soma:=0; Parcela:=DuasCasasDecimaisExtended(t/n); for i:=1 to n-1 do begin cds.Append; cds.FieldByName(´valorEmReal´).AsFloat:=r; cds.Post; //Como é um comando For .. as PArcelas1 + Parcelas2+parcelas3 etc... //São somadas a Variável Soma soma:=Soma+parcela; end; //A Variavel Soma contem o Valor da Ultima Parcela , Soma:=ValorTotal - Soma; cds.Append; cds.FieldByName(´ValorReal´).AsFloat:=Soma; cds.Post; end;
14/05/2008
Rb2228
If (i = QtdeParcelas) Then {DuasCasasDecimais, é uma função criada que trunca o valor em duas casas após a vírgula} DMEntradaNota.CdsPagamentoNota.FieldByName(´CDPNVALORPARCELA´).AsFloat := DMEntradaNota.CdsEntradaNota.FieldByName(´CDENVALORNOTA´).AsFloat - varSomaParcelas {Se nao for a ultima parcela} Else begin DMEntradaNota.CdsPagamentoNota.FieldByName(´CDPNVALORPARCELA´).AsFloat := DMEntradaNota.CdsEntradaNota.FieldByName(´CDENVALORNOTA´).AsFloat / QtdeParcelas; varSomaParcelas := varSomaParcelas + DMEntradaNota.CdsPagamentoNota.FieldByName(´CDPNVALORPARCELA´).AsFloat; end;
Perfeito! Deu certo... tanto com valores inteiros como quebrados.
Salles, me desculpe, não havia entendido muito bem no post anterior
mas agora sim, Obrigado!
Clique aqui para fazer login e interagir na Comunidade :)