DELPHI四舍五入问题解决


本文整理自网络,侵删。

 这段时间在用DELPHI做一个财务系统时发现每一行的小计取了两位小数后与用SQL的ROUND查询出来的不一样,在程序中是用FormatFloat('0.00',ItemSum)函数来取值的,再用DXDBGRID网格显视合计,最终与SELECT SUM(ROUND(ITEMSUM,2))得出的结果是不一样的。

例如ItemSum:=1.005,在程序FormatFloat('0.00',ItemSum)就返回是“1”,应该是“1.01”才是。

因为以前做的系统都没有用DXDBGIRD来显视合计, 一直都没留意这个问题,然后新建了一个程序来测试,用FormatFloat('0.00',1.005)得出是“1.01”是正确的,这是怎么回事呢,将1.005付给变量ItemSum再FormatFloat('0.00',ItemSum)就返回是“1”,单步调试时ItemSum一直都是1.005,通过变量同一个数据就有不同的结果。

一开始ItemSum是Double类型的,后来改为Extended后FormatFloat('0.00',ItemSum)就返回是“1.01”了,为什么会这样呢,后来想了一下可能是Double类型,因为在计算机中数是用二进制存储的,而十进制的有限小数转换成二进制可能变成无限小数,所以存储的时候会有一定的误差。在通常情况下,如果要比较两个数的大小,必须通过对它们的求差得到,如比较ItemSum1与ItemSum是否相等,应用abs(ItemSum1-ItemSum1)<0来判断。1.005就变成了1.004999999999999....了。

使用Extended或者FormatFloat('0.00',StrToFloat(FlotToStr(ItemSum)))就解决问题了。

**************************

在DELPHI中Round()和RoundTo()都是四舍五入的函数,但DELPHI用的四舍五入与一般的四舍五入不同,它采用的是四舍六入五留双。

即当舍或入位大于或小于五时按四舍五入来处理,而当舍或入位等于五时,就要看前面一位是什么,根据奇进偶不进,它总是返回一个偶数值。

这种算法其实是按照银行家算法,统计学上一般都用这种算法,比传统的"四舍五入"要科学。在VB、.net相关的语言中都有这个问题。

例如:

表达式 返回值

Round(11.5) 12

Round(10.5) 10

RoundTo(1234567, 3) 1234000

RoundTo(1.234, -2) 1.23

RoundTo(1.235, -2) 1.24

RoundTo(1.245, -2) 1.24

如果要使用传统的"四舍五入"方法,可以使用下面函数:

function RoundEx(R: Real): Int64;

begin

Result:= Trunc(R);

if Frac(R) >= 0.5 then

Result:= Result + 1;

end;

function DRound(const Value: Extended; const Digit: Byte = 0): Extended;

var

tmp: Extended;

begin

tmp := Power(10, Digit);

if Value > 0 then

Result := Value * tmp + 0.5

else

Result := Value * tmp - 0.5;

Result := Trunc(Result) / tmp;

end;

相关阅读 >>

Delphi xe中使用tchart绘制平滑曲线

dbgrid导出excl表

Delphi 常用函数单元 umyfunctions

Delphi xe 程序瘦身.编译后exe最低90kb

Delphi serial number of an usb flash drive 获取u盘硬件序列号

Delphi cef4Delphi 浏览器事件

Delphi xe berlin readprocessmemory writeprocessmemory

Delphi 提取字符串中所有数字

Delphi之memo组件

Delphi ado的事务处理例子

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...