I have found a strange behavior of Delphi's FormatFloat function. Let me show the case study.
value to be converted : 129809.495
formatted output desired : 129,809.50
Case 1 : Converting from a string
var str: string;
str := '129809.495';
str := FormatFloat(',0.00', StrToFloat(str));
// output is 129,809.50 = CORRECT
Case 2 : Converting from a double variable
var number: double;
str: string;
val := 129809.495;
str := FormatFloat(',0.00', val);
// output is 129,809.50 = CORRECT
Case 3 : Converting from a dataset's field
*it's too complex to write here, let me just explain*
Basically the formatted output of FormatFloat(',0.00', Dataset.Field[0].AsFloat);
always resulted in 129,809.49 == WRONG
I've been testing this behavior using SQL Server 2008 & Firebird 1.5.
Component used are ADO Components and UniDAC components (by DevArt), and all have the same behavior.
I've tried to do these :
But all resulted in same wrong conversion .49 instead of .50
1 way that works is
val := StrToFloat(Dataset.Field[0].AsString);
FormatFloat(',0.00', val);
Has anyone got a solution for this behavior? Because it'd be too much work to force convert StrToFloat and then reformat the variable/output. And this workaround can't be applied to 3rd party components that were using FormatFloat
Any help appreciated. Thanks
It looks like it is related to some precision differences between Double and Extended. Actually I cannot confirm your observation about case 2 being correct. Perhaps because you declare a variable number as double, but then use a variable val of unknown type.
Anyway, the following code
var
d: Double;
e: Extended;
begin
d := 129809.495;
e := 129809.495;
Writeln(FormatFloat(',0.00', d));
Writeln(FormatFloat(',0.00', e));
e := d;
Writeln(FormatFloat(',0.00', e));
e := 129809.495;
d := e;
Writeln(FormatFloat(',0.00', d));
end;
compiled with XE6 produces the following output:
129,809.49
129,809.50
129,809.49
129,809.49
This leads to the conclusion that a double is not able to hold the correct value to be rounded as expected, while an extended is more suitable. In addition, when the value is once stored in double format, simply converting it to extended (that is what happens with FormatFloat) doesn't heal the rounding error.