以下示例演示了该问题:
var
fdt, fndt : Double;
dt, dt2 : TDateTime;
begin
dt := EncodeDateTime(2023, 12, 31, //
20, 10, 5, 100);
dt2 := EncodeTime(20, 10, 5, 100);
fdt := Frac(dt);
fndt := Frac(dt2);
Memo1.Lines.Add('Equal: ' + BoolToStr(fdt = fndt, True) + CRLF + //
FloatToStr(fdt) + CRLF + //
FloatToStr(fndt) + CRLF + //
FormatDateTime('HH:NN:SS ZZZ', fdt) + CRLF + //
FormatDateTime('HH:NN:SS ZZZ', fndt) + CRLF + //
''
);
Exit;
结果是:
Equal: False
0,840336805558763
0,840336805555556
20:10:05 100
20:10:05 100
因此,正如您所看到的,时间部分与 Double 不同,但与格式化字符串相同。
为什么它们不同?
据我所知,EncodeDateTime 执行的是 EncodeDate + EncodeTime。并且 Date = Trunc(Date)。因此小数部分必须相同!但事实并非如此。为什么?也许是一些时区信息?
感谢您提供关于此的任何信息。
环境:Win 11,Delphi S10,32 位 Exe。时区:欧洲/布达佩斯 (+2/+1)。
由于浮点类型的不准确性,使用运算符比较浮点值是否相等
=
通常并不准确。仅仅因为输入相同并不能保证浮点数相同。您必须考虑 epsilon 来判断浮点值是否“足够接近”以被视为相等。您可以将其用于
Math.SameValue()
此目的。但是,在这种情况下,你可以使用
DateUtils.SameTime()
或DateUtils.CompareTime()
代替。SameTime()
文档甚至说明了以下内容: