arredondamento - não consigo chegar a 100¬
Preciso colocar a porcentagem de alguns itens em um grid, por exemplo:
item1 R$ 100,00 12,5¬
item2 R$ 250,00 31,25¬
item3 R$ 450,00 56,25¬
total R$ 800,00
apresento qto representa cada valor em ¬ sobre o valor total...
a minha lista tem mais de 60 itens, com valores diversos....
testei 3 formas de arredondamento e em nenhum deles consegui totalizar 100¬
rotinas utilizadas:
1)
function TForm1.Arredondar(value: double; casas: integer): double;
Var fracao:real;
decimal:string;
begin
try
fracao:=Frac(value); //Retorna a parte fracionária de um número
decimal:=(RightStr(floattostr(fracao),length(floattostr(fracao))-2)); //decimal recebe a parte decimal
//enquanto o tamanho da variavel decimal for maior que o número de casas faça
while length(decimal) > casas do
begin
//Verifica se o último digito da variável decimal é maior que 5
if strtoint(RightStr(decimal,1))>5 then
begin
//Descarta o último digito da variável Decimal
decimal:=leftstr(decimal,length(decimal)-1);
//Soma o valor número da variavel decimal + 1
decimal:=floattostr(strtofloat(decimal) + 1);
end
else
decimal:=leftstr(decimal,length(decimal)-1); //Descarta o último digito da variável Decimal
end;
result:=(int(value) + (strtofloat(decimal)/100)); //devolve o resultado para a função
except
Raise Exception.Create(´Erro no arredondamento´);
end;
end;
2)
RoundNExtend(valor,2);
3)
function TForm1.TBRound(Value: Extended; Decimals: integer): Extended;
var
Factor, Fraction: Extended;
begin
Factor := IntPower(10, Decimals);
{ A conversão para string e depois para float evita
erros de arredondamentos indesejáveis. }
Value := StrToFloat(FloatToStr(Value * Factor));
Result := Int(Value);
Fraction := Frac(Value);
if Fraction >= 0.5 then
Result := Result + 1
else if Fraction <= -0.5 then
Result := Result - 1;
Result := Result / Factor;
end;
em todas uso duas casas decimais....
o mais proximo que chego é 99,94¬
alguem tem alguma sugestão ???? ja fiz algumas pesquisas no forum tbem, mas não consegui solucionar este problema....
item1 R$ 100,00 12,5¬
item2 R$ 250,00 31,25¬
item3 R$ 450,00 56,25¬
total R$ 800,00
apresento qto representa cada valor em ¬ sobre o valor total...
a minha lista tem mais de 60 itens, com valores diversos....
testei 3 formas de arredondamento e em nenhum deles consegui totalizar 100¬
rotinas utilizadas:
1)
function TForm1.Arredondar(value: double; casas: integer): double;
Var fracao:real;
decimal:string;
begin
try
fracao:=Frac(value); //Retorna a parte fracionária de um número
decimal:=(RightStr(floattostr(fracao),length(floattostr(fracao))-2)); //decimal recebe a parte decimal
//enquanto o tamanho da variavel decimal for maior que o número de casas faça
while length(decimal) > casas do
begin
//Verifica se o último digito da variável decimal é maior que 5
if strtoint(RightStr(decimal,1))>5 then
begin
//Descarta o último digito da variável Decimal
decimal:=leftstr(decimal,length(decimal)-1);
//Soma o valor número da variavel decimal + 1
decimal:=floattostr(strtofloat(decimal) + 1);
end
else
decimal:=leftstr(decimal,length(decimal)-1); //Descarta o último digito da variável Decimal
end;
result:=(int(value) + (strtofloat(decimal)/100)); //devolve o resultado para a função
except
Raise Exception.Create(´Erro no arredondamento´);
end;
end;
2)
RoundNExtend(valor,2);
3)
function TForm1.TBRound(Value: Extended; Decimals: integer): Extended;
var
Factor, Fraction: Extended;
begin
Factor := IntPower(10, Decimals);
{ A conversão para string e depois para float evita
erros de arredondamentos indesejáveis. }
Value := StrToFloat(FloatToStr(Value * Factor));
Result := Int(Value);
Fraction := Frac(Value);
if Fraction >= 0.5 then
Result := Result + 1
else if Fraction <= -0.5 then
Result := Result - 1;
Result := Result / Factor;
end;
em todas uso duas casas decimais....
o mais proximo que chego é 99,94¬
alguem tem alguma sugestão ???? ja fiz algumas pesquisas no forum tbem, mas não consegui solucionar este problema....
Arc
Curtidas 0
Respostas
Emerson Nascimento
19/01/2007
para chegar ao percentual você precisa ter o valor total previamente calculado, certo?
de posse desse valor, faça algo assim:
// duas casas decimais
usando RoundTo():
percentual := RoundTo( (valoritem / valortotal) * 100, -2 );
calculo direto:
percentual := Round( (valoritem / valortotal) * 10000 ) / 100;
ou
// três casas decimais
usando RoundTo():
percentual := RoundTo( (valoritem / valortotal) * 100, -3 );
calculo direto:
percentual := Round( (valoritem / valortotal) * 100000 ) / 1000;
(a função RoundTo() está na unit Math)
quanto maior o número de casas decimais, mais o valor será aproximado.
de posse desse valor, faça algo assim:
// duas casas decimais
usando RoundTo():
percentual := RoundTo( (valoritem / valortotal) * 100, -2 );
calculo direto:
percentual := Round( (valoritem / valortotal) * 10000 ) / 100;
ou
// três casas decimais
usando RoundTo():
percentual := RoundTo( (valoritem / valortotal) * 100, -3 );
calculo direto:
percentual := Round( (valoritem / valortotal) * 100000 ) / 1000;
(a função RoundTo() está na unit Math)
quanto maior o número de casas decimais, mais o valor será aproximado.
GOSTEI 0
Arc
19/01/2007
caro emersom, corrigindo, eu usei o RoundTo e não RoundNExtend...
RoundNExtend é o nome de uma outra função que tbem testei anteriormente.
se eu usar o RoundTo com duas casas decimais, ele não totaliza 100¬
com 3 casas sim, o problema esta na hora de exibir os valores, pois uso a mascara #,0.00¬ para exibi-los com duas casas, ..., se vc somar a coluna, vai chegar no mesmo valor se fizesse o arredondamento com duas casas.
RoundNExtend é o nome de uma outra função que tbem testei anteriormente.
se eu usar o RoundTo com duas casas decimais, ele não totaliza 100¬
com 3 casas sim, o problema esta na hora de exibir os valores, pois uso a mascara #,0.00¬ para exibi-los com duas casas, ..., se vc somar a coluna, vai chegar no mesmo valor se fizesse o arredondamento com duas casas.
GOSTEI 0
Eng_diehl
19/01/2007
Desculpe me intrometer mas acho que isso é um problema matematico e nao de programação.
Veja bem, quando voce arredonda um valor segundo convenções matemáticas acontece o seguinte:
5,77 = 5,8
5,44 = 5,4
4,46 = 4,5
3,55 = 3,6
Isto significa que a probabilidade da soma dos seus valores arredondados ser igual a dos valores originais é extremamente remota.
Sugiro que voce faça uma rotina que escolha o menor valor de todos os dados que formam o seu 100¬. Para o calculo da porcentagem exclua este valor some o restante. Calcule a porcentagem deste somatorio e diminua de 100¬. Voce terá uma aproximação muito boa, já que matematicamente nunca conseguirá um resultado melhor que este com arredondamentos.
Qualquer coisa estou ai...
Abraçoo
Veja bem, quando voce arredonda um valor segundo convenções matemáticas acontece o seguinte:
5,77 = 5,8
5,44 = 5,4
4,46 = 4,5
3,55 = 3,6
Isto significa que a probabilidade da soma dos seus valores arredondados ser igual a dos valores originais é extremamente remota.
Sugiro que voce faça uma rotina que escolha o menor valor de todos os dados que formam o seu 100¬. Para o calculo da porcentagem exclua este valor some o restante. Calcule a porcentagem deste somatorio e diminua de 100¬. Voce terá uma aproximação muito boa, já que matematicamente nunca conseguirá um resultado melhor que este com arredondamentos.
Qualquer coisa estou ai...
Abraçoo
GOSTEI 0
Eng_diehl
19/01/2007
Uma saida interessante é voce utilizar o somatório dos valores arredondados como o teu 100¬.
Dai fecha tb....
Dai fecha tb....
GOSTEI 0