Getting two outputs instead of one in Matlab - matlab

The question here was to find if the date provided is a valid one or not without using native Matlab date functions. I was hoping if someone can point out my mistake here. I'm also getting the "Output argument valid (and maybe others) not assigned during call to valid_date" error in Matlab learning tool when I submit it.
function valid = valid_date(year,month,day)
if nargin~=3
valid = false;
elseif ~isscalar(year)||year<1||year~=fix(year)
valid = false;
return
elseif ~isscalar(month)||month<1||month~=fix(month)
valid = false;
return
elseif ~isscalar(day)||day<1||day~=fix(day)
valid = false;
return
elseif month>12 || day > 31
valid = false;
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
leapdata=1;
else
leapdata=0;
end
%the below if statements are used to define the months. Some months have
%31 days and others have 30 days, while February has only 28 days and 29 on
%leap years. this is checked in the below code.
% I feel the below code is where the error is.
if ismember (month, [1 3 5 7 8 10 12])
ismember (day, (1:31))
return
elseif ismember( month, [4 6 9 11])
ismember (day, (1:30))
return
end
if month == 2
if leapdata==1
ismember (day, (1:29))
return
elseif leapdata==0
ismember (day, (1:28))
return
else
valid = false;
end
end

When returning at the end of a Matlab function, the value of the variable valid is sent as an output. In the lines below the four comments, you need to assign the variable to true or false inside of the if statements. For example:
if ismember(month, [1 3 5 7 8 10 12])
valid = ismember(day, (1:31))
return
elseif ismember(month, [4 6 9 11])
valid = ismember(day, (1:30))
return
end
if month == 2
if leapdata == 1
valid = ismember(day, (1:29))
return
elseif leapdata == 0
valid = ismember(day, (1:28))
return
else
valid = false;
end
end

Related

How do you get "1" as integer in if-else statement rather than as boolean in MATLAB?

I am trying to use MATLAB FUNCTION block in simulink .
The model is shown below
In the "time_calc" Function i want to manipulate the variable "Sector" as shown in the code below
if sector == 1 || 2
sec = 1
elseif sector == 3 || 4
sec = 2
elseif sector == 5||6
sec = 3
elseif sector == 7||8
sec = 4
elseif sector == 9||10
sec = 5
elseif sector == 11 || 12
sec = 6
end
The below is the scope and you can see the values of "sector" changing from 0 through 12 and then repeating itself
But I am getting the value of "sec" as constant "1"(shown below in figure)
(Maybe because it is evaluating the first "1" as boolean true and running that statement only over and over again)
How to correct it ?
if sector == 1 || 2 evaluates sector == 1, if it's true, the statement is true. If it's false, it evaluates 2, which is always true, and so the statement is always true.
What you intended to write was if sector == 1 || sector == 2. You can also write this as if any(sector == [1, 2]).
Your function is equivalent to:
sec=ceil(sector/2)
#Cris Luengo's answer shows why your code is wrong. But I suggest you change the entire thing by this one liner, that is much clearer.
Remove the elseif's and replace them all with just if's

Test for scalar function inputs is failing

Despite using isscalar, isinteger... the result after running is still true, I still had this test which is incorrect and in relation with Scalar values.
My program:
function valid = valid_date(year, month, day)
[y1 y2] = size(year);
[m1 m2] = size(month);
[d1 d2] = size(day);
if (mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0
is_leap_year = 1;
else
is_leap_year = 0;
end
if ~(y1==y2==d1==d2==m1==m2==1)
valid = false;
elseif any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31)
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif month == 2 && is_leap_year == 1
valid = (day >0 && day <=29);
elseif month == 2 && is_leap_year == 0
valid = (day >0 && day <=28);
else
valid = false;
end
end
The result after submitting my program, all tests are passed except the one related to scalar values:
Why did my program fail on the non-scalar test?
The way you're checking for scalars is really not well defined.
~(y1==y2==d1==d2==m1==m2==1)
This chained equivalence check is not the same as checking if all of your variables are equal to 1, consider the following counter-example:
1==0==0==1 % Output: 1
In this case none of your comparison variables should be 0, so you might skirt this issue, but it's still best to avoid it. You're also contending with floating point comparisons which are prone to issues.
You should use isscalar, you say you tried it but didn't show how. Something like this should work:
function valid = valid_date(year, month, day)
if ~( isscalar(year) && isscalar(month) && isscalar(day) )
valid = false;
return
end
% ... other code now we know inputs are scalar
end
Thank you so much #Wolfie. The problem is solved.
I used what you told me about and put it at the beginning of my function.
I show you guys the code, in case you had the same error:
function valid = valid_date(year, month, day)
if ~(isscalar(year) && isscalar(month) && isscalar(day))
valid = false;
return
end
if ((mod(year,4)==0 && mod(year,100)~=0) || mod(year,400)==0)
is_leap_year = 1;
else
is_leap_year = 0;
end
if any(month == [1, 3, 5, 7, 8, 10, 12])
valid = (day >0 && day <= 31);
elseif any(month == [4, 6, 9, 11])
valid = day >0 && day <= 30;
elseif (month == 2 && is_leap_year == 1)
valid = (day >0 && day <=29);
elseif (month == 2 && is_leap_year == 0)
valid = (day >0 && day <=28);
else
valid = false;
end
end
Yaaay all the tests are passed lhamdullah!

Function that take date and return the statement of the validation of the date

Write a function called valid_date that takes three positive integer scalar inputs year, month, day. If these three represent a valid date, return a logical true, otherwise false. The name of the output argument is valid. If any of the inputs is not a positive integer scalar, return false as well. Note that every year that is exactly divisible by 4 is a leap year, except for years that are exactly divisible by 100. However, years that are exactly divisible by 400 are also leap years. For example, the year 1900 was not leap year, but the year 2000 was. Note that your solution must not contain any of the date related built-in MATLAB functions.
samples:
valid = valid_date(2018,4,1)
valid = valid_date(2018,4,31)
The outputs are :
valid =
logical
1
valid =
logical
0
Here is a partial solution:
function valid= valid_date(year,month,date)
if nargin~=3
valid=false;
elseif ~isscalar(year) | ~isscalar(month) | ~isscalar(date)
valid=false;
elseif year<1 || month<1 || date<1
valid=false;
elseif year~=fix(year) || month~=fix(month) || date~=fix(date)
valid=false;
elseif month>12 || date>31
valid=false;
elseif month==2
if (rem(year,400)==0 || (rem(year,4)==0 && rem(year,100)~=0)) && date<30
valid=true;
elseif (rem(year,400)~=0 || (rem(year,4)~=0 && rem(year,100)==0)) && date<29
valid=true;
else
valid=false;
end
else
days = [31 29 31 30 31 30 31 31 30 31 30 31];
totaldays = days(month);
if date>totaldays
valid=false;
else
valid=true;
end
end
end
My solution is:
function out= valid_date(y,m,d)
if mod(y,4)==0
if mod (y,100)==0
if mod(y,400)==0
leap =true;
else
leap=false;
end
else
leap =true;
end
else
leap= false;
end
if y>0 &m>0&d>0 &y==fix(y)&m==fix(m)&d==fix(d)&m<=12 &isscalar(y)&isscalar(m)& isscalar(d)
if (m==1 | m==3|m==5|m==7 |m==8 |m==10 |m==12)&d <=31
out=true;
elseif d<=30
if m==2
if leap==true & d<=29
out =true;
elseif leap==false &d<=28
out=true;
else
out=false;
end
else
out=true;
end
else
out =false;
end
else
out= false;
end

Matlab Code for weekdays and weekends [duplicate]

This question already has an answer here:
Weekend extraction in Matlab
(1 answer)
Closed 6 years ago.
I were able to successfully made a schedule in which the output is 1 if time is between 7 AM-5PM and otherwise 0, time is based on my computer. However the day Monday-Sunday is based on my computer as well.. I cant find the solution to put an output 1 on Monday-Saturday and output 0 on Sunday. The code I have is below
function y = IsBetween5AMand7PM
coder.extrinsic('clock');
time = zeros(1,6);
time = clock;
current = 3600*time(4) + 60*time(5) + time(6); %seconds passed from the beginning of day until now
morning = 3600*7; %seconds passed from the beginning of day until 7AM
evening = 3600*17; %seconds passed from the beginning of day until 5PM
y = current > morning && current < evening;
end
Now the time here is correct already what I need is for the day (Monday-Sunday) to have my needed output. Also this matlab code is inside a matlab function on Simulink block.
If you use weekday like this, you can generate a 0/1 value as you specified for today's date:
if (weekday(now) > 1)
day_of_week_flag = 1;
else
day_of_week_flag = 0;
or if you like, this one-liner does the same thing, but may not be as easy to read if you're not familiar with the syntax:
day_of_week_flag = ( weekday(now) > 1);
You can also use date-strings like this to convert other dates:
day_of_week_flag = ( weekday('01-Mar-2016') > 1 )
Finally, if you have a numeric array of date/time values, like [2016 3 3 12 0 0], you first need to convert to a serial date using datenum, then use weekday:
time = clock;
day_of_week_flag = ( weekday(datenum(time)) > 1);
An alternate way to check without using weekday is the following:
time = clock;
day_of_week = datestr(time, 8);
if (day_of_week == 'Sun')
day_of_week_flag = 0;
else
day_of_week_flag = 1;

How do I fix this error: "Undefined function or variable 'NaN'"?

I'm getting an error message in the yellow highlighted region that says "Undefined function or variable 'NaN'".
The purpose of this code is to determine the amount of change to give back to a customer. This is based on how much an item costs and how much was paid. Also, the code should return a flag saying if the transaction was completed.
This isn't all of my code, but I didn't want to make this longer than necessary.
Can anyone tell me what's wrong?
function [Change, flag] = makeChange(Cost, Paid)
extra = Paid-Cost;
if extra > 0
Change = extra;
flag = true;
elseif extra == 0
Change = 0;
flag = true;
return
else
flag = false;
Change = NaN;
warning('That''s not enough to buy that item.');
return
end
I couldn't confirm the problem with Octave 3.8.1.
octave:1> makeChange.m
error: 'Paid' undefined near line 4 column 9
error: called from:
error: /Path/to/makeChange.m at line 4, column 7
octave:1> Cost = 5
Cost = 5
octave:2> Paid = 10
Paid = 10
octave:3> [change, completed] = makeChange(Cost, Paid)
change = 5
completed = 1
octave:4> Cost = 10
Cost = 10
octave:5> Paid = 5
Paid = 5
octave:6> [change, completed] = makeChange(Cost, Paid)
warning: That's not enough to buy that item.
change = NaN
completed = 0
I would recommend reformatting your code to the following:
function [Change, flag] = makeChange(Cost, Paid)
Change = Paid-Cost;
flag = true;
if Change < 0
flag = false;
Change = NaN;
warning('That''s not enough to buy that item.');
return
else
return
end
By refactoring, you save yourself some needless comparisons, assignments, and logic.