奇怪的日期添加行为

Posted

技术标签:

【中文标题】奇怪的日期添加行为【英文标题】:Bizarre DateAdd behavior 【发布时间】:2015-03-20 21:35:19 【问题描述】:

谁能解释以下结果:

?DateAdd("s", 54, 0) = #12:00:54 AM#
True

?DateAdd("s", 55, 0) = #12:00:55 AM#
False

?DateAdd("s", 56, 0) = #12:00:56 AM#
True

更新:Ross Presser 的回答提供了什么:差异与二进制分数不能总是代表十进制分数这一事实有关。但是为什么当两个表达式计算为相同的数据类型时浮点偏移量不同

?TypeName(DateAdd("s", 55, 0))
Date

?TypeName(#12:00:55 AM#)
Date

?VarType(DateAdd("s", 55, 0)) = VarType(#12:00:55 AM#)
True

当我遇到这种浮点工件in 和past 时,通常是因为结果实际上是两种不同的类型,至少在评估期间的某个时候是这样。这似乎不是这里的情况。我还是一头雾水。

更新 2:Ross 的更新答案提供了对该问题的更多见解。我在追踪这个方面取得了进展。每个答案似乎都提出了新的问题。似乎 DateAdd 和日期文字都使用双精度,但由于某种原因,DateAdd 舍入到小数点后 18 位(或者可能在 19 处截断并且根本不舍入):

?CDbl(#12:00:55 AM#) - CDbl(55/86400)
 0 

?CDbl(DateAdd("s", 55, 0)) - CDbl(55/86400)
-1.0842021724855E-19 

?0.000636574074074074 - 0.0006365740740740741
-1.0842021724855E-19 

任何想法为什么会出现这种情况?

【问题讨论】:

一个肮脏的小技巧来解决这个问题是使用? ("" & dateadd("s", 55, 0)) = #00:00:55# 【参考方案1】:

Date 在 VBA 中表示为整数天数加上代表时间的浮点分数。由于时间是一个浮点数(或者可能是一个双精度数),它不能以完美的精度准确地表达每一秒。 55 秒是 55/86400,或一天的 0.00063657407。这可能无法在浮点数中精确表示。

要获得更多信息,请尝试从字面值中减去 Dateadd 值,然后转换为浮点数。

编辑:这是我所说的见解:

? cdbl(dateadd("s",55,0)) - cdbl(#12:00:55 AM#)
-1.0842021724855E-19 

将时间文字转换为 Date 结构的解析算法显然与 dateadd 函数所做的不同,导致小数点后第 19 位出现错误。我的猜测是其中一个或另一个在应该使用 Double 的地方使用 Single。我想你可以称这是一个错误并将其报告给 Microsoft。

编辑 2:谷歌搜索出现了this link,人们在其中谈论 VBA 日期类型下的浮点现实。他们举了一个不同的例子,错误在第 17 位而不是第 19 位:

? DateAdd("h",2,#8:00#) - #10:00#
-5.55111512312578E-17 

还有this gentleman 编写了一些VBA 代码来更准确地完成DateAdd 的工作。 (该页面上的站点以格式错误的代码块显示代码,该代码块会破坏所有换行符,但该代码是可下载的。)

【讨论】:

我明白了其中的一部分(+1 给你)。我想我仍然不明白的是为什么这两种形式不是都以同样的方式受到浮点偏移的影响。请查看我更新的问题。 我再次更新了我原来的问题。我不希望您对我的更新有权威的解释,但我很想听听您的想法。

以上是关于奇怪的日期添加行为的主要内容,如果未能解决你的问题,请参考以下文章

phpmyadmin 自动递增主键行为奇怪

添加到 std::vector 时类字段的奇怪行为

核心数据:使用延迟实例化时的奇怪错误行为

在 viewDidLoad 中添加子视图有奇怪的行为 [重复]

将 UIButton 添加到 UICollectionViewCell 时的奇怪行为

将彩色 UIImageView 添加到 UITableViewCell 时的奇怪行为