MATLAB: Function takes far too long to run, and then doesn’t write all the values to a text document.

for loopfprintffunctionif statementMATLABtime

Hello,
I have 2 functions, one which tests to see if a year is a leap year, and another that generates a list of leap years based on a start and end date, then writes this to a text document. The problem I'm having is that the code works, but the list function takes about 20 seconds to run, and then doesn't write all the information to the text document if the start and end years are too far apart. The codes are as follows:
To test to see if a year is a leap year
function [ LY ] = IsLeapYear( Y )
%IsLeapYear.m, determines if a year is a leap year, Craig, 02/05/2017
x = Y/400; %sets value for x
z = Y/100; %sets value for z
w = Y/4; %sets value for w
x_1 = ~mod(x,1); %finds if x is an interger
z_1 = ~mod(z,1); %finds if z is an interger
w_1 = ~mod(w,1); %finds if w is an interger
% 1) All years evenly divisible by 400 are leap years.
if x_1 == 1; %if x is an interger
LY = true; %makes LY true

%3) Years divisible by 4 but not by 100 are leap years.
elseif (w_1 == 1) && (z_1 == 0); %if w is an interger and z is not an interger
LY = true; %makes LY true
%2) Years evenly divisible by 100 but not by 400 are not leap years.
elseif x_1+z_1==0; %if either x or z are not intergers
LY = false; %makes LY false
%4) All other years are not leap years.
else LY = false; %all other values for LY are false
end
end
and to generate the list of leap years then write it to a text file:
function [ GetLY ] = GetLeapYears( startYear, endYear )
%GetLeapYears.m, generates a list of leap years, Craig Munt, 02/05/2017
% uses function IsLeapYear to generate and output a list of leap years the write those years to a text file
GetLY = (startYear:endYear); %makes GetLY an array thats between the start and end years with steps of 1 year
fid = fopen('GetLeapYears.txt','w'); %Creates the text file GetLeapYears.txt and prepares it to be written to
for n=1:length(GetLY) %creates variable n loop between the values of 1 and the length of GetLY
if (IsLeapYear(GetLY(n))) == 1; %checks if the year is a leap year using the IsLeapYear function
fprintf(fid, '%g\t',GetLY(:,n)); %prints a column of the table
else GetLY(:,n)=0; %if it is not a leapyear, it sets its value to 0
end
end
GetLY( : , ~any(GetLY,1)) = []; %deletes any columns that =0
fclose(fid); %closes the text file GetLeapYears.txt from editing
end
Thanks in advance,
Craig

Best Answer

Your code runs fine for me (and write all the entries to the file)
>>tic; GetLeapYears(0, 10000); toc;
Elapsed time is 0.055957 seconds.
So it must be a problem with your machine or location where you're writing the file.
Notwithstanding the speed issue, your code could substantially be improved.
In your GetLeapYears function, you sometimes use GetLY(n) sometimes GetLY(:, n). Be consistent!. Since GetLY is a row vector the colon is never needed.
Similarly, in your IsLeapYear function you sometimes use logical operations on logicals (e.g. (w_1 == 1) && (z_1 == 0)) and sometimes use arithmetic operations: elseif x_1+z_1==0. That latter expression is equivalent to elseif ~x_1 & ~x_2.
Also, since w_1 is logical , w_1 == 1 is the same as w_1 and z_1 == 0 is the same as ~z_1.
The main issue with your IsLeapYear function is that it can only operate on one year at a time, forcing you to use a loop in the other function. If you use simple boolean logic instead of if ... else, you can write a very simple IsLeapYear function that works on many dates at once, speeding up the code (which is already fast):
function LY = IsLeapYear(Y)
LY = mod(Y, 400) & mod(Y, 100) & ~mod(Y, 4)
end