DELPHI四舍五入问题解决
转自http://www.delphitop.com/html/jichu/153.html 感谢原作者。
这段时间在用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;
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现