- 註冊時間
- 2006-3-13
- 最後登錄
- 2025-1-10
- 在線時間
- 673 小時
- 閱讀權限
- 200
- 積分
- 417
- 帖子
- 1107
- 精華
- 0
- UID
- 2
  
|
參考來源 http://d.02t.cn/html/jczs/1188.html
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;
複製代碼 |
|