Delphi的四舍五入函数Round有BUG,无法正常工作。
对于XXX.5的情况,整数部分是奇数,那么会Round Up,偶数会Round Down,例如:
x:= Round(17.5) = x = 18
x:= Round(12.5) = x = 12
请使用下面的函数代替Round:
function DoRound(Value: Extended): Int64;
procedure Set8087CW(NewCW: Word);
asm
MOV Default8087CW,AX
FNCLEX
FLDCW Default8087CW
end;
const
RoundUpCW = $1B32;
var
OldCW : Word;
begin
OldCW := Default8087CW;
try
Set8087CW(RoundUpCW);
Result := Round(Value);
finally
Set8087CW(OldCW);
end;
end;
BORLAND的ROUND函数只能取整,而且是统计学上的四舍五入(奇数进,偶数不进),
应用中很不方便,大家提出了很多解决方案,综合起来主要有以下几种:
1.先换算成整数再用round处理,再换算回原来的数据
存在问题:round的取整算法和常用的不一样
2.先换算成整数再+0.5,再用INT处理,再换算回原来的数据
存在问题:很多人编写的函数没有处理负数
3.用FORMATFLOAT函数处理
存在问题:一般的数据均能处理,也是很多人认为的正确的答案,
但如果处理的是运算结果,因运算结果是浮点数,可能存在误差,则结果就不对.
例:显示是1.085,但运算结果可能是1.08499999,则取两位小数的结果为1.08
在总结上述错误,参观论坛上各高手的论述,我提出我的终极四舍五入函数,
我认为是全面的,但可能还有错误,或有更简单的算法,欢迎大家批评指教!
function RoundFloat(f:double;i:integer):double;
var
s:string;
ef:extended;
begin
s:='#.'+StringOfChar('0',i);
ef:=StrToFloat(FloatToStr(f));//防止浮点运算的误差
result:=StrToFloat(FormatFloat(s,ef));
end;
上面函数有问题(在取整并且结果为0的时候出错),现修正如下:
function RoundFloat(f:double;i:integer):double;
var
s:string;
ef:extended;
SValue: string;
begin
s:='#.'+StringOfChar('0',i);
ef:=StrToFloat(FloatToStr(f));//防止浮点运算的误差
SValue := FormatFloat(s,ef);
if SValue <> '' then
result := StrToFloat(SValue)
else
result := 0;
end;
这些都是以往贴子上的好见解,你看一下吧