I'm using Orpheus controls in my app. When the user enters 40.085, for
example, the control displays 40.09. I checked their source, they are
calling Str to format the double for display.
I asked, why do that since Str rounds up, and the rest of Delphi depends on
the processor and does banker's? All my replies have been, "When I try what
you are doing, I see banker's rounding."
So I wrote the following - can anyone tell me what they get when they use it
both with BankerRound true and false? BankerRound = false always rounds up
for me, using the Str() call. TurboPower seems to be claiming it always does
Banker's Round. If they are correct - then the following function should
always banker's round, regardless of the BankerRound param:
function RoundCurrency(Value: currency; DecimalPlaces: integer;
BankerRound: boolean): currency;
var
Factor : Extended;
Width: integer;
SResult: string;
begin
if DecimalPlaces > 3 then
DecimalPlaces := 3
else if DecimalPlaces < 0 then
DecimalPlaces := 0;
Factor := Power(10, DecimalPlaces);
if BankerRound then
Result := Round(Value * Factor) / Factor
else begin
Width := Length(FloatToStr(Trunc(Value)));
Str((Value * Factor):Width:0, SResult);
Result := StrToCurr(SResult) / Factor;
end;
end;
This statement is slightly inaccurate, and is probably the source of your
frustrations. How the CPU performs rounding can be changed by setting a
control bit, and I've heard that several MS DLLs set this bit.
> can anyone tell me what they get when they use it both with
> BankerRound true and false?
uses
Math;
function RoundCurrency(Value: currency; DecimalPlaces: integer;
BankerRound: boolean): currency;
var
Factor : Extended;
Width: integer;
SResult: string;
begin
if DecimalPlaces > 3 then
DecimalPlaces := 3
else if DecimalPlaces < 0 then
DecimalPlaces := 0;
Factor := Power(10, DecimalPlaces);
if BankerRound then
Result := Round(Value * Factor) / Factor
else begin
Width := Length(FloatToStr(Trunc(Value)));
Str((Value * Factor):Width:0, SResult);
Result := StrToCurr(SResult) / Factor;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FloatToStr(RoundCurrency(40.085, 2, True))); // 4.08
ShowMessage(FloatToStr(RoundCurrency(40.085, 2, False))); // 4.09
end;
Ah ... thanks for this tidbit. I thought I'd read in the Intel instruction
set that this was configurable. I hadn't heard about the .dll part.
> > can anyone tell me what they get when they use it both with
> > BankerRound true and false?
> procedure TForm1.Button1Click(Sender: TObject);
> begin
> ShowMessage(FloatToStr(RoundCurrency(40.085, 2, True))); // 4.08
> ShowMessage(FloatToStr(RoundCurrency(40.085, 2, False))); // 4.09
> end;
You get rounding up with Str() then, too.
See, if the control bit was in play - I couldn't get banker's rounding with
this routine - because it relies on Round which relies on the processor.
The Orpheus control uses Str() - ... - thanks for the feedback - I'll have
to see what those guys come back with.
Do you know why Str() rounds up instead of obeying the processor? Does it
use (a) different instruction(s)?