Delphi - 使用FormatFloat('0.##',argValue)时不一致的浮点舍入

bej*_*run 1 delphi

尝试使用函数FormatFloat(格式字符串'0.##')将double值四舍五入到小数点后两位.

以下是inputoutput

231.545 -> 231.54 (but expected output is 231.55)
2.315 -> 2.31 (but expected output is 2.32)

23.045 -> 23.05 (gives expected output 23.05)
23.145 -> 23.14 (but expected output 23.15)

23.245 -> 23.25 (gives expected output 23.25)
23.345 -> 23.34 (but expected output 23.35)

23.445 -> 23.45 (gives expected output 23.45)
23.545 -> 23.55 (gives expected output 23.55)
23.645 -> 23.65 (but expected output 23.64)

23.745 -> 23.75 (gives expected output 23.75)
23.845 -> 23.84 (but expected output 23.84)
23.945 -> 23.95 (gives expected output 23.95)

为什么会发生这种奇怪的行为?我正在使用Delphi 7.

LU *_* RD 5

二进制浮点值不能完全代表每个值.这就是你所看到的.

例如,该值2.315以双精度表示:

2.31499 99999 99999 94670 92948 17992 48605 96656 79931 64062 5
Run Code Online (Sandbox Code Playgroud)

这将四舍五入 2.31


如果您可以使用十进制数据类型,currency则可以获得所需的输出(如果货币在您的工作范围的限制范围内):

var
  c : Currency;
begin
  c := 2.315;
  WriteLn(FormatFloat('0.##',c)); // Outputs 2.32
end.
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用小数库,如BigDecimals,但这需要一个现代的Delphi版本,并支持带方法的记录.