フィルターのクリア

How to write a function that only accepts non-negative integer

11 ビュー (過去 30 日間)
JGraf
JGraf 2017 年 2 月 26 日
編集済み: Bruno Luong 2023 年 8 月 18 日
Hi,
I am writing a function called day_diff that takes four scalar positive integer inputs, month1, day1, month2, day2. These represents the birthdays of two people who were born in 2015. The function returns a positive integer scalar that is equal to the difference between the ages of the two people in days. So far I have solved the first part (calculating the days), which I don't need help with. However I need to make sure to check that the input values are of the correct types and they represent valid dates. If they are erroneous, I need the function to return -1.
I am having issues testing the inputs e.g. m1 and m2 to be between 1 and 12 and being integers. d1 and d1 must be between d1<=h(1,m1) && d1>0 and integers.
I have tried using mod(m1,1)==1 and ~scalar but I got myself way to deep into something that I think should be relatively simple? I have a feeling that a test for a positive integer can be done more efficiently? Any help is greatly appreciated.
I am not allowed to use the built-in function datenum or datetime.
my code is as follows:
function dd=day_diff(m1,d1,m2,d2)
h=[31,28,31,30,31,30,31,31,30,31,30,31];
if m1>12 mod(m1,1)==1; dd=-1 end
if m2>m1
dd=sum(h(m1+1:1:m2))-(m2-d2)+(m1-d1)+1;
elseif m1>m2
dd=sum(h(m2+1:1:m1))-(m1-d1)+(m2-d2);
elseif m1==m2 && d1>=d2
dd=d1-d2;
else
dd=d2-d1;
end

回答 (1 件)

Jan
Jan 2017 年 2 月 26 日
編集済み: Jan 2017 年 2 月 27 日
The problem gets easier, if you work with the cumulative number of days:
h = [31,28,31,30,31,30,31,31,30,31,30,31];
% hc = cumsum([0, h(1:11)])
hc = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
Then a date is day of the year:
day1 = d1 + hc(m1);
Now a subtraction is easy and you can use abs() to get rid of the sign.
I'd suggest to reject months lower than 1 and greater than 12, days lower than 1 and greater than the allowed range, e.g. d1 > h(m1). Then set dd to -1 and return; immediately.
To test for integers use: x ~= round(x)
  3 件のコメント
Jan
Jan 2017 年 2 月 27 日
編集済み: Jan 2017 年 2 月 27 日
Check the integer value of m1 before you access h(m1).
v = [m1, d1, m2, d2]; % Easier to test it for all 4 inputs
if any(v ~= round(v));
dd = -1;
return
end
Check the valid day afterwards in this order:
if d1<1 || d1>h(m1) % Not d1>h(m1) || d1<1
because h(m1) fails if m1 is < 1. The OR operator applies a "short-circuting": If the first operand is TRUE, the second is not evaluated anymore.
Your calculation of the number of days is not correct.
day_diff(2,1, 1,1)
replies 27 instead of the correct 31. Compare it with:
abs(datenum([2015, m1, d1]) - datenum([2015, m2, d2]))
In sum(h(m1+1:1:m2))-(m2-d2)+(m1-d1)+1 the value of h(m2) should not matter and neither m2 nor m1 should appear directly. Only the difference of the day numbers and the number of days from the months m1 to m2 matter. Try sum(h(m1:m2-1)) + d2 - d1. But then it matters, if d1 is greater then d2 or vice versa, such that even more case differentiations are required.
As said already, datenum([2015, m1, d1]) can be calculated by the cheap: d1+hc(m1) using hc from my answer. You do not need any case differentiation then, but a single line of code is enough (plus the definition of hc).
Danai Riga
Danai Riga 2017 年 11 月 19 日
編集済み: Bruno Luong 2023 年 8 月 18 日
Hi all, this worked for me in the end.
function [ dd ] = day_diff( m1, d1, m2, d2 )
% Input represents the birthdays of two children who were born in 2015
% dd: the difference between the ages of the two children in days
v=[31 28 31 30 31 30 31 31 30 31 30 31]; % days in the 12 months of 2015
if nargin<4;
dd=-1;
return
end
if ~isscalar(m1) || m1<1 && m1>12 || m1~=fix(m1) || m1<=0;
dd=-1;
return
end
if ~isscalar(m2) || m2<1 && m2>12 || m2~=fix(m2) || m2<=0 ;
dd=-1;
return
end
if ~isscalar(d1) || 1<d1 && d1>v(m1) || d1~=fix(d1) || d1<=0 ;
dd=-1;
return
end
if ~isscalar(d2) || 1<d2 && d2>v(m2) || d2~=fix(d2) || d2<=0 ;
dd=-1;
return
end
vc = cumsum([0, v(1:11)]); % cummulative days in the 12 months of 2015
day1 = d1 + vc(m1); % which day of the year is d1
day2 = d2 + vc(m2); % which day of the year is d2
if day1>=day2;
dd=day1-day2;
elseif day2>=day1;
dd=day2-day1;
end
end

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeBirthdays についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by