Why does adding time directly to datenum not add the anticipated amount of time?
7 views (last 30 days)
Show older comments
Matlab time is stored as a numerical value in units of days since 00-Jan-0000. Going on this premise, why is it that when I add 1/1400 (the value of one minute as there are 1400 minutes in a day) that occasionally I will lose a second.
For example
mytime = datenum('03-04-2015','mm-dd-yyyy'); % mytime should equal 736027
If I systematically add 1/1400 to this datenum (the value of one minute as there are 1400 minutes in a day), the time will not change minute by minute. This can be shown easily with the following loop.
for i = 1:1440
mytime = mytime + 1/1440;
if ~strcmp(datestr(mytime,'SS'),'00')
disp(i)
disp(datestr(mytime,'dd-mm-yyyy HH:MM:SS')
break
end
end
On the 137th iteration, a full second is dropped. I can effectively add time using the datenum or minutes function, setting it to one minute and adding that, but it takes significantly longer and isn't especially efficient. I'm working with a large amount of data and adding time using this method makes my program run way too slow. Why is this happening and how can I get around it without crippling my runtime?
0 Comments
Accepted Answer
Guillaume
on 24 Jun 2015
Edited: Guillaume
on 24 Jun 2015
Most likely 1/1440 can not be represented exactly in binary, so every time you add it, you've got a small rounding error. These rounding errors accumulate to the point you loose a second after a while.
It's a fact that fractions can not be represented exactly by a computer (using double) so you should avoid summing small numbers. Note for example that:
s = 0
for i = 1:10, s = s + 0.1 end
s == 1
returns false due to the accumulation error after just 10 iterations.
What about using date vectors (or datetime) instead of datenum? They both use integer representation for hours, minutes and seconds.
1 Comment
More Answers (1)
James Tursa
on 24 Jun 2015
Edited: James Tursa
on 24 Jun 2015
I will advise using Guillaume's suggestion (datevec or datetime), but will point out that you are not losing a full 1 sec of accuracy after only 137 iterations. Your printed date & time value is a truncated one. E.g., after running your code for 140 iterations and using a different format that prints out the fraction of seconds I get this:
mytime = datenum('03-04-2015','mm-dd-yyyy'); % mytime should equal 736027
mytime0 = mytime;
for i = 1:1440
mytime = mytime + 1/1440;
if ~strcmp(datestr(mytime,'SS'),'00')
disp(i)
disp(datestr(mytime,'dd-mm-yyyy HH:MM:SS.FFF'))
break
end
end
140
04-03-2015 02:19:59.999
So it is much closer to the '00' value than you think. E.g.,
>> 86400*(mytime-mytime0)
ans =
8399.99949932098
0 Comments
See Also
Categories
Find more on Time Series Objects in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!