Arredondamento financeiro no Delphi
É muito comum encontrar programadores Delphi que têm dúvidas sobre como arredondar um valor real para “n” casas após o separador decimal. A princípio parece um problema simples, pois o próprio Delphi já possui uma função que arredonda para o inteiro mais próximo, a qual poderia facilmente ser utilizada para arredondar para qualquer quantidade de casas decimais. Exemplo:
{ x receberá o valor de y arredondado para 2 casas após o separador. }
x := Round(y * 100) / 100;
{ z receberá o valor de y arredondado para 3 casas após o separador. }
z := Round(y * 1000) / 1000;
No entanto dois problemas poderão aparecer com os exemplos acima:
- O arredondamento feito pelo Delphi difere daquele feito pelas calculadores financeiras, bem como bancos de dados como InterBase e FireBird.
- poderão ocorrer pequenos arredondamentos devido ao modo como o Delphi trata números reais, tais como aparecer 3.9999999… em vez de 4.
A função abaixo resolve estes dois problemas.
{ Esta função faz arredondamento de valores reais para "n" casas
decimais após o separador decimal, seguindo os critérios das
calculadoras financeiras e dos bancos de dados InterBase e FireBird.
}
function 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;