使用VBA Now与Now()时的时差?

需要了解为什么我有时间差异。 这是我的VBA代码:

Public OHLCArray(1 To 481, 0 To 28, 0 To 3) As Single 'debug stmt below Dim DebugTime As Double OHLCArray(1, 0, 3) = Now() 'next 3 lines are debugging lines DebugTime = OHLCArray(1, 0, 3) Print #1, "Now()=" & DebugTime Print #1, Now & "Debug print line - (just before pushing" 

以下是日志文件中的debugging输出行:

  Now()=42527.4609375 06/06/2016 11:01:00 AMDebug print line - (just before pushing 

只是你知道,时间0.4609375 = 11:03:45 AM; 我期待在第二次印刷声明中的“现在”向我展示这一点,或者不超过2秒钟左右。

我的问题:在上面的例子中,为什么我会得到不同的时间? 现在和现在()有区别吗? 这能否影响时间的捕捉,就像上面显示的那样?

谢谢你的帮助。 卡尔。

PS以下是在上面确定的行之前的2个debugging输出行:

  06/06/2016 10:59:34 AM - Skipped ws_calculate routine - CurrentTimeID already processed - CurrentTimeID = 45 06/06/2016 10:59:54 AM - Skipped ws_calculate routine - CurrentTimeID already processed - CurrentTimeID = 45 

PSS这是一个有点相关的话题的链接 – 不知道它是否适用于我的问题: Postgres now()vs'now'in function

PSS感谢Vegard。 在查看其他具有类似输出数据的日志文件后,可以确定我的混淆是由于两个错误引起的:a)在将新的单一数据移动到它之前,我没有将DebugTime重置为零(小数位从单个被重叠到双?),和b)你的观察,单数据types转移到双数据types没有用,因为截断全date数据发生时,它是最初移动到我的数组定义为Single。 我想我会保持我的arrays为单一的,但是,为了避免它的大小加倍,当我的数组99.8%的工作正好被定义为单一。 我可以在我的表格的头文件中接受最多2分钟的时间(当数组传送到它时)。 我已经知道,在大多数应用程序中将date/时间数据移动到单一数据types是不够的。 数据types应该是Double或DateTime。

PSS Final:今天(星期三,上​​午11点左右)用debugging语句运行的逻辑向我展示了以下内容:OHLCArray(1,0,3)= Now()
OHLCArray元素为Single捕获date.time为42529.46。 现在()然而是42529.45905067(相当于上午11:01:02),这出现在我的print.debug和打印日志文件(正确)。 现在被铸造,它四舍五入到.46。
DebugTime = OHLCArray(1,0,3)
当数组元素被输出到DebugTime时,其他数字被拾取(错误)。 DebugTime = 42529.46093750。 这意味着上午11:03:45。 这里也是有趣的地方。 当我将该数组元素(42529.46)稍后移动到我的Excel工作表(反映完整数组的表单)时,我得到表格中的上午11点03分45秒,这个单元格被格式化为只显示数字。 所以这意味着工作表中的单元格以与DebugTime = OHLCArray(1,0,3)语句完全相同的方式接收数字。 因为记住,数组元素是42529.46。 0.46转换为上午11:02:24。

感谢VeGard的所有额外的努力。 我希望这个后续的内容能帮助你更深入的了解EXCEL和VBA的一些不那么明显的方式。 正如我总是告诉我的非计算机知识的朋友:“电脑从来没有错!

在date的上下文中使用Single可以给你正确的答案的任何情况都是极端的巧合。

为了进一步说明为什么,在Gary的答案的基础上,我颠倒了你的代码,使得数组声明是Double – 这使得我们想要比较实际上正确的DoubleSingle -cast-to- Double正确。

 Sub testTime() Dim OHLCArray(1 To 481, 0 To 28, 0 To 3) As Double 'debug stmt below Dim DblTime As Double, SngTime As Single OHLCArray(1, 0, 3) = Now() 'next 3 lines are debugging lines DblTime = OHLCArray(1, 0, 3) SngTime = OHLCArray(1, 0, 3) Debug.Print "Doubletime: " & DblTime Debug.Print "Singletime: " & SngTime Debug.Print " Date Double Single Double(single2)" Debug.Print "Singletime = " & CDate(SngTime) & " - " & CDbl(SngTime) & " - " & CSng(SngTime) & " - " & CDbl(SngTime2) Debug.Print "Doubletime = " & CDate(DblTime) & " - " & CDbl(DblTime) & " - " & CSng(DblTime) Debug.Print "Now() = " & Now() & " - " & CDbl(Now()) & " - " & CSng(Now()) Debug.Print "Now = " & Now & " - " & CDbl(Now) & " - " & CSng(Now) End Sub 

现在,让我们回顾一下输出。 我已经运行了好几次,这清楚地说明了这个问题。 观察在“Double”列的第一行中发生了什么(或者说什么也没有发生),这就是我们将单个单元转换为double的地方,并将其与下一行中的Double进行比较:

 Doubletime: 42528,3991666667 Singletime: 42528,4 Date Double Single Singletime = 07.06.2016 09:33:45 - 42528,3984375 - 42528,4 Doubletime = 07.06.2016 09:34:48 - 42528,3991666667 - 42528,4 Now() = 07.06.2016 09:34:48 - 42528,3991666667 - 42528,4 Now = 07.06.2016 09:34:48 - 42528,3991666667 - 42528,4 Doubletime: 42528,3995138889 Singletime: 42528,4 Date Double Single Singletime = 07.06.2016 09:33:45 - 42528,3984375 - 42528,4 Doubletime = 07.06.2016 09:35:18 - 42528,3995138889 - 42528,4 Now() = 07.06.2016 09:35:18 - 42528,3995138889 - 42528,4 Now = 07.06.2016 09:35:18 - 42528,3995138889 - 42528,4 Doubletime: 42528,3996180556 Singletime: 42528,4 Date Double Single Singletime = 07.06.2016 09:33:45 - 42528,3984375 - 42528,4 Doubletime = 07.06.2016 09:35:27 - 42528,3996180556 - 42528,4 Now() = 07.06.2016 09:35:27 - 42528,3996180556 - 42528,4 Now = 07.06.2016 09:35:27 - 42528,3996180556 - 42528,4 Doubletime: 42528,3998726852 Singletime: 42528,4 Date Double Single Singletime = 07.06.2016 09:33:45 - 42528,3984375 - 42528,4 Doubletime = 07.06.2016 09:35:49 - 42528,3998726852 - 42528,4 Now() = 07.06.2016 09:35:49 - 42528,3998726852 - 42528,4 Now = 07.06.2016 09:35:49 - 42528,3998726852 - 42528,4 Doubletime: 42528,4045486111 Singletime: 42528,41 Date Double Single Singletime = 07.06.2016 09:45:00 - 42528,40625 - 42528,41 Doubletime = 07.06.2016 09:42:33 - 42528,4045486111 - 42528,41 Now() = 07.06.2016 09:42:33 - 42528,4045486111 - 42528,41 Now = 07.06.2016 09:42:33 - 42528,4045486111 - 42528,41 

请注意,对于使用Single所有date转换,由于数据types不能支持足够的数字,因此时间戳实际上是长时间静态的。

将其转换为Double的事实可以产生更多的数字并不一定就是正确的 – 它会变得稍微准确一些,但仍然不正确。

所以这个问题似乎与NowNow() ! 如我的例子所示,只要使用正确的数据types,它们都会产生正确的结果。

您的第一个问题,不正确的时间戳,是由arrays是一个而不是一个Double

你的第二个问题是完全的,也许在你的代码中。 要么你正在重载Now或者更可能的是, Print在运行时正在做一些有趣的事情。 尝试使用Debug.Print "Now: " & Now初始化Print语句,然后将结果与日志文件进行比较,或者按照文档更好地更改:

Print #1, Now & "Debug print line - (just before pushing"

对此:

Print #1, CDate(Now) & "Debug print line - (just before pushing"

date数据使用系统识别的标准短date格式写入文件。 当date或时间组件缺失或零时,只有提供的部分被写入文件。

编辑:

至于在Single to Double中出现的神秘的额外数字,这不是编译器所做的近似值,因为我之前错误地猜到了。 数字如何表示是一个已知的副作用,这在计算机科学中是一个显而易见的常见话题 。

对于数字精度,请使用Decimal数据types 。

MSDN特别在Visual Basic上下文中详细讨论了浮点精度。

这里: https : //msdn.microsoft.com/en-us/library/system.double.aspx?cs-save-lang=1&cs-lang=vb#Conversions

types转换。 Double结构为IConvertible接口提供了一个明确的接口实现,它支持任意两个标准.NET Framework数据types之间的转换。 语言编译器还支持将所有其他标准数值types的值隐式转换为Double值。 将任何标准数值types的值转换为Double是一个扩展转换,不需要使用铸造操作符或转换方法的用户。

但是,Int64和Single值的转换可能会导致精度损失。

精度问题最经常影响转换为Double值的单个值。

在这里: https : //msdn.microsoft.com/en-us/library/system.single.aspx

例如,2/10作为小数部分表示为0.0011111001001100作为二元分数,模式“1100”重复为无穷大。 在这种情况下,浮点值提供了它所表示的数字的不精确表示。 对原始浮点值执行额外的math运算往往会增加其精度的不足。 例如,如果将乘以.3乘以10的结果与将.3乘以.3乘以9的结果相比较,则会看到加法运算得到的结果精度较低,因为它涉及八次以上的乘法运算。 请注意,只有在使用“R”标准数字格式string显示两个单值时,这种不一致才是显而易见的,如果需要,显示单一types支持的全部9位精度。

使用Single而不是Double产生了一些截断:

 Sub NotNow() Dim s As Single, d As Double s = Now d = Now Dim dt As Date, dt2 As Date dt = CDate(s) dt2 = CDate(d) MsgBox s & vbCrLf & d & vbCrLf & dt & vbCrLf & dt2 End Sub 

在这里输入图像说明

Now和Now()之间没有区别。 您的示例中的差异是因为OHLCarray被声明为单个。 当我宣布事物是双倍的时候是相同的:

现在()= 42528.3594907407
42528.3594907407debugging打印行 – (就在推动之前)

(顺便说一句,如果你想准确的时间使用Windows API调用高分辨率定时器)

 Sub lg() Dim OHLCArray(1 To 481, 0 To 28, 0 To 3) As Double 'debug stmt below Dim DebugTime As Double OHLCArray(1, 0, 3) = Now() 'next 3 lines are debugging lines DebugTime = OHLCArray(1, 0, 3) Debug.Print "Now()=" & DebugTime Debug.Print CDbl(Now) & "Debug print line - (just before pushing" End Sub