Why does adding time directly to datenum not add the anticipated amount of time?

7 views (last 30 days)
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?

Accepted Answer

Guillaume
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
Stephen23
Stephen23 on 24 Jun 2015
Edited: Stephen23 on 24 Jun 2015
Seconds can contain fractional values too, according to datevec: "milliseconds are a fractional part of the seconds...".

Sign in to comment.

More Answers (1)

James Tursa
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

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!