创建日期向量时的舍入问题

Rounding problems when creating date vectors

我想在 matlab 中创建一个包含日期的向量。为此,我指定了开始时间和停止时间:

WHM01_start = datenum('01-JAN-2005 00:00')
WHM01_stop = datenum('01-SEP-2014 00:00')

然后我用

创建了向量
WHM01_timevec = WHM01_start:datenum('01-JAN-2014 00:20') - datenum('01-JAN-2014 00:00'):WHM01_stop;

我希望每个时间步长为 20 分钟。不幸的是,我在几千个值后出现舍入错误,导致我

>> datestr(WHM01_timevec(254160))

ans =

31-Aug-2014 23:39:59

和预期的不一样,31-Aug-2014 23:40:00
我该如何更正这些不正确的值?

编辑:我也看到了这个 thread,但不幸的是我得到了每个日期的矢量,而不是所需的数字。

您可以将年、月、日...以数字格式提供给函数 datenum。 Datenum 的一个或多个参数接受向量,如果数字太大(例如 120 分钟),datenum 知道如何处理它。

因此,通过以 20 分钟为增量提供分钟向量,您可以避免舍入错误(至少在 1 秒级别):

WHM01_start = datenum('01-JAN-2005 00:00');
WHM01_stop = datenum('01-SEP-2014 00:00');

time_diff = WHM01_stop - WHM01_start;

WHM01_timevec = test = datenum(2005,01,01,00,[00:20:time_diff*24*60],00);

datestr(WHM01_timevec(254160))

回答您的评论:

您看到舍入错误的原因是您使用了两个大数字的差作为时间增量。大数之差有(相对)大的舍入误差。

Matlab 时间从(虚构的)日期 0.0.0000 开始以天数计算。您的时间增量为 1/3 小时,或 1/(24*3) 天。修改您的原始代码,使其显示为

WHM01_timevec = WHM01_start:1/(24*3):WHM01_stop;

是减少舍入误差的另一种方法,但对于荒谬的大时间跨度,第一种解决方案是一种更可靠的方法。

Related answer: use linspace instead of the colon operator :.

%// given
WHM01_start = datenum('01-JAN-2005 00:00')
WHM01_stop = datenum('01-SEP-2014 00:00')

%// number of elements
n = numel(WHM01_start: datenum('01-JAN-2014 00:20') - ...
                       datenum('01-JAN-2014 00:00') : WHM01_stop);

%// creating vector using linspace
WHM01_timevec = linspace(WHM01_start, WHM01_stop, n);

%// proof
datestr(WHM01_timevec(254160))

ans =

31-Aug-2014 23:40:00

此解决方案的缺点:为了确定输出向量的元素数量,我使用了用 : 创建的原始向量,这可能不是最佳选择。


链接答案中的重要引述:

使用linspace可以降低这些问题发生的概率,不是安全的