Valid_date function

조회 수: 13 (최근 30일)
Denise Gobbo
Denise Gobbo 2020년 5월 18일
댓글: Rik 2021년 9월 22일
I am having some troubles with the logical operators in "day". What could I do to solve it?
function valid = valid_date(year, month, day)
if ~isinteger(year)
if ~isinteger(month)
if ~isinteger(day)
if ~isscalar(year)
if ~isscalar(month)
if ~isscalar(day)
valid = false;
elseif month == 2
if ((rem(year,4)== 0) && (rem(year,100) ~= 0)) || (rem(year,400)==0)
(1 <= day) && (day <= 28);
valid = true;
else
(1 <= day) && (day <= 29);
valid = true;
end
elseif month == 1 || 3 || 5 || 7 || 8 || 10 || 12
(1 <= day)&(day <= 31);
valid = true;
elseif month == 4 || 6 || 9 || 11
1 <= day <= 30;
valid = true;
else
valid = false;
end
end
end
end
end
end
end
  댓글 수: 4
the cyclist
the cyclist 2020년 5월 18일
Personal preference, perhaps, but I actually like keeping the indenting of the isinteger if statements. To my mind, they are a logical grouping and easier to interpret as that group if they appear at the same level if indentation. Similarly, I usually write
for x = 1:10
for y = 1:10
% do something in x-y space
end
end
because x and y are "on equal footing" as spatial coordinates.
Of course, the point is moot because I'm pretty certain that all those if statements are the not the logic that OP is intending to implement.
Adam Danz
Adam Danz 2020년 5월 18일
편집: Adam Danz 2020년 5월 18일
Thanks for sharing that perspective, @the cyclist . I can see how that grouping can be helpful when the conditional statements are fully nested. If there are additional lines of code outside of the nested structure, I bet it would become difficult to read, though.
eg
for x = 1:10
for y = 1:10
for z = 1:10
% do something in x-y-z space
end
% some code here
end
% some code here
end

댓글을 달려면 로그인하십시오.

답변 (6개)

Thyagharajan K K
Thyagharajan K K 2020년 6월 2일
valid = valid_date(2019, 12, 1)
function valid = valid_date(year,month,day)
%check if either year, month, day is not a scalar
if ~isscalar(year) || ~isscalar(month) || ~isscalar(day)
valid =false
return
end
%check if either year, month, day is 0 or negative. check if month is >12
if year<=0 || month>12 || month <=0 ||day<=0
valid =false
return
end
A = [1 3 5 7 8 10 12]; %months with 31 days
B = [4 6 9 11]; %months with 30days
month_31d = sum(ismember(A,month));
%ismember() returns a logical array where element found will be marked as 1 & other positions will be 0
%so only one element in this logical array will be 1 and other elements will be 0 if month falls in this
%month_31d category. Hence sum will be 1 i.e month_31d will be true.
month_30d = sum(ismember(B,month)); %same as above to check whether month falls in the category month_30d
%check for leap year
if rem(year,400)==0
leap_year = true;
elseif rem(year,4)==0 && rem(year,100) ~=0
leap_year =true;
else
leap_year = false;
end
%Check the days for the conditions 28,29,30,31
if month_31d && day>31
valid = false;
elseif month_30d && day>30
valid = false;
elseif (leap_year && month==2 && day>29)||(~leap_year&&month==2&&day>28)
valid = false;
else
valid =true;
end
end
  댓글 수: 1
Walter Roberson
Walter Roberson 2021년 3월 21일
Needs improvement.
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
0
function valid = valid_date(year,month,day)
%check if either year, month, day is not a scalar
if ~isscalar(year) || ~isscalar(month) || ~isscalar(day)
valid =false
return
end
%check if either year, month, day is 0 or negative. check if month is >12
if year<=0 || month>12 || month <=0 ||day<=0
valid =false
return
end
A = [1 3 5 7 8 10 12]; %months with 31 days
B = [4 6 9 11]; %months with 30days
month_31d = sum(ismember(A,month));
%ismember() returns a logical array where element found will be marked as 1 & other positions will be 0
%so only one element in this logical array will be 1 and other elements will be 0 if month falls in this
%month_31d category. Hence sum will be 1 i.e month_31d will be true.
month_30d = sum(ismember(B,month)); %same as above to check whether month falls in the category month_30d
%check for leap year
if rem(year,400)==0
leap_year = true;
elseif rem(year,4)==0 && rem(year,100) ~=0
leap_year =true;
else
leap_year = false;
end
%Check the days for the conditions 28,29,30,31
if month_31d && day>31
valid = false;
elseif month_30d && day>30
valid = false;
elseif (leap_year && month==2 && day>29)||(~leap_year&&month==2&&day>28)
valid = false;
else
valid =true;
end
end

댓글을 달려면 로그인하십시오.


the cyclist
the cyclist 2020년 5월 18일
편집: the cyclist 2020년 5월 18일
This syntax
1 <= day <= 30
does not check if day is between 1 and 30. You need to do that as two separate checks:
(1 <= day) & (day <= 30);
as you did in the other sections.
Also, for this chain of if statements:
if ~isinteger(year)
if ~isinteger(month)
if ~isinteger(day)
if ~isscalar(year)
if ~isscalar(month)
if ~isscalar(day)
I think you probably actually want a single if statement:
if ~isinteger(year) || ~isinteger(month) || ~isinteger(day) ... and so on
valid = false
end
The way your code is written, if year is an integer, then your function will simply exit, never having evaluated the output variable valid.

Adam Danz
Adam Danz 2020년 5월 18일
"I am having some troubles with the logical operators in "day"."
That doesn't give us enough background infomation to know what the problem is. Does that mean you're getting an error? The wrong value? The wrong class? An empty output? Is it causing your compute to explode? etc. We can help you more quickly if you tell us what the problem is.
That being said, there are lots of problems with this code and the the problems I immediately see have nothing to do with the 'day' variable.
For example, let's say Year is an interger but Month is not. Read through your code and estimate what would happen. Hint: no output at all.
If you want to return a value of false when the inputs aren't in the correct format,
if ~isinteger(year) || ~isinteger(month) || . . . || ~isscalar(month)
valid = false;
else
% [main part of your code]
end
If you want to determine if the month is 1,3,5,7,8,10 or 12,
if ismember(month, [1 3 5. . .]);
If you want to define values based on differet sets of months,
switch month
case 2
% your code
case {1 3 5 . . .}
% your code
case {4 6 9 . . .}
% your code
otherwise
error('Month did not meet any of the case requrements.')
end

Himanshi Singh
Himanshi Singh 2020년 9월 6일
function valid = valid_date (year, month, date)
if ~(isscalar(year) && isscalar(month) && isscalar(date))
valid=false;
elseif year ~= fix(year) || year<1
valid=false;
elseif month ~= fix(month) || month<1 || month>12
valid=false;
elseif date ~= fix(date) || date<1 || date>31
valid=false;
elseif (month == 4 || month == 6 || month == 9 || month == 11) && date>30
valid = false;
elseif month == 2 && ((year/4 ~= fix(year/4) || (year/100 == fix(year/100) && year/400 ~= fix(year/400))) || date>29)&&date>28
valid = false;
else
valid = true;
end
  댓글 수: 2
Rik
Rik 2020년 9월 6일
Why did you post a complete solution to a homework question without any explanation? Now your answer is only useful for people wanting to cheat.
Walter Roberson
Walter Roberson 2021년 3월 21일
Better than some, but could still use improvement.
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
ans = logical
1
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
1
function valid = valid_date (year, month, date)
if ~(isscalar(year) && isscalar(month) && isscalar(date))
valid=false;
elseif year ~= fix(year) || year<1
valid=false;
elseif month ~= fix(month) || month<1 || month>12
valid=false;
elseif date ~= fix(date) || date<1 || date>31
valid=false;
elseif (month == 4 || month == 6 || month == 9 || month == 11) && date>30
valid = false;
elseif month == 2 && ((year/4 ~= fix(year/4) || (year/100 == fix(year/100) && year/400 ~= fix(year/400))) || date>29)&&date>28
valid = false;
else
valid = true;
end
end

댓글을 달려면 로그인하십시오.


Ahmed Saleh
Ahmed Saleh 2021년 3월 21일
편집: Ahmed Saleh 2021년 3월 21일
function valid = valid_date(year,month,day)
y= year;
m=month;
d=day;
days_1=[31 28 31 30 31 30 31 31 30 31 30 31];
if (fix(y/4)==(y/4) && fix(y/100)~=(y/100)) || (fix(y/4)==(y/4) && fix(y/100)==(y/100) && fix(y/400)==(y/400))
days_1(2)=29;
end
if ~isscalar(y) || ~isscalar(m) || ~isscalar(d)
valid= false;
return
elseif y<=0 || m<=0 || d<=0 || m>12 || d>31
valid = false;
return
elseif days_1(m)<d
valid=false;
return
else
valid=true;
end
  댓글 수: 4
Walter Roberson
Walter Roberson 2021년 3월 21일
Rik, please leave this one, as my unit tests are instructive.
Rik
Rik 2021년 3월 21일
@Walter Roberson I agree, and have consequently remove the flag.

댓글을 달려면 로그인하십시오.


Kabir Puri
Kabir Puri 2021년 9월 22일
% this is my answer
function valid = valid_date(year, month, day);
if day<=0 || month <=0 || ~isscalar(year) ||~isscalar(month)||~isscalar(day)||mod(day,1)~=0 ||mod(month,1)~=0||mod(year,1)~=0;
valid = false;
elseif month>12;
valid = false;
elseif (month==1 || month==3|| month==5||month==7||month==8||month==10||month==12)&& day>31;
valid = false;
elseif (month==4||month==6||month==9||month==11)&&day>30;
valid = false;
elseif (month == 2 && ((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) ) && day>29
valid =false;
elseif month== 2 && ~((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) && day>28;
valid= false;
else;
valid =true;
end;
  댓글 수: 1
Rik
Rik 2021년 9월 22일
I added an extra end to your function, but after that it passes almost all the unit tests by Walter (you only missed the complex-valued input) and you missed my addition (different datatype).
So now only the question remains why you decided to post this solution to a homework question?
try valid_date(nan,nan,nan), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234.56,1,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1.23,7), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(1234,1,7.89), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(2021,2,7+3i), catch ME; disp(ME.message); end
Arguments must be real.
try valid_date(inf,2,29), catch ME; disp(ME.message); end
ans = logical
0
try valid_date(struct,2,28), catch ME; disp(ME.message); end
Undefined function 'mod' for input arguments of type 'struct'.
function valid = valid_date(year, month, day);
if day<=0 || month <=0 || ~isscalar(year) ||~isscalar(month)||~isscalar(day)||mod(day,1)~=0 ||mod(month,1)~=0||mod(year,1)~=0;
valid = false;
elseif month>12
valid = false;
elseif (month==1 || month==3|| month==5||month==7||month==8||month==10||month==12)&& day>31
valid = false;
elseif (month==4||month==6||month==9||month==11)&&day>30
valid = false;
elseif (month == 2 && ((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) ) && day>29
valid =false;
elseif month== 2 && ~((mod(year,4)==0 && mod(year,100)~=0)||(mod(year,400)==0)) && day>28
valid= false;
else
valid =true;
end
end

댓글을 달려면 로그인하십시오.

카테고리

Help CenterFile Exchange에서 Dates and Time에 대해 자세히 알아보기

태그

Community Treasure Hunt

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

Start Hunting!

Translated by