Arredondamento de Valor. Onde?

13/05/2008

0

Pessoal, tenho o seguinte codigo:

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

Rb2228

Responder

Posts

13/05/2008

Marco Salles

amigo não sei se entend ibem o que voce quer mas veja a diferença
entre as duas funçoes abaixo..


function DuasCasasDecimais(valor : real) : real; begin result := Trunc(Valor * 100) / 100; end;


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...


Responder

14/05/2008

Webjoel

Olá!

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.



Responder

14/05/2008

Rb2228

Salles,
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.


Responder

14/05/2008

Rb2228

Webjoel, eu utilizo a função DuasCasasDeciamais para truncar o valor, e não arredondar. De qualquer modo, obrigado.


Responder

14/05/2008

Edilcimar

Por que você não pega o valor total, subtrai das parcelas anteriores, o resto será automaticamente o valor da última prestação
Ex: ValorTotal := 100, Parcela1 = 100/3, Parcela2 = 100/3 e Parcela3 = ValorTotal - Parcela1 - Parcela2


Responder

14/05/2008

Marco Salles

Amigo , fiz aqui rapidinho com o ClientDataSet em Memoria e não obtive nenhum problema

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...


Responder

14/05/2008

Rb2228

Salles,
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]


Responder

14/05/2008

Marco Salles

Salles, não sei se concorda, mas o Edilcimar tem razão. uma forma mais simplificada de se fazer.


edicilmar escreveu:
Por que você não pega o valor total, subtrai das parcelas anteriores, o resto será automaticamente o valor da última prestação Ex: ValorTotal := 100, Parcela1 = 100/3, Parcela2 = 100/3 e Parcela3 = ValorTotal - Parcela1 - Parcela2


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;



Responder

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!


Responder

Assista grátis a nossa aula inaugural

Assitir aula

Saiba por que programar é uma questão de
sobrevivência e como aprender sem riscos

Assistir agora

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar