生れてから今日まで、何日生きてきただろう!
1.誕生日からの経過日の計算方法
プログラミングを勉強するときにプログラミング言語(例えば、C言語)を覚えることは大切ですが、一番重要なのは、計算させる処理の手順(アルゴリズム)を考える思考力を養うことです。
それでは、誕生日からの経過日を求める処理について、考えていきましょう。
誕生日を「2001年12月5日」とし、今日の日付を「2004年7月5日」とした場合を例として、図1を参考に経過日を求める処理を考えます。
図1 経過日
図中に示すように、経過日を三つの期間(@、A、B)に分けると、経過日を次のような計算式によって求めることができるようになります。
経過日の計算
@誕生日の年における1月1日から誕生日までの経過日数
A誕生日の年の1月1日から当該日(今日)の前年12月31日までの経過日数
B当該日(今日)の年における1月1日からの経過日数
経過日 = A
+ B - @
この三つの期間をそれぞれ求めればよいわけですが、よく見ると@とBの期間については、同様な処理によって求めることが可能です。つまり、1月1日からの経過日を計算すればよいのです。
では、簡単なAの期間から求めてみましょう。
2.A誕生日の年の1月1日から当該日(今日)の前年12月31日までの経過日数
うるう年を考慮しなければなりませんが、これを無視して求めるとすると、平年の1年間は、365日ですので、次の式によってAの期間の経過日を求めることができます。
変数
BYear:誕生日(年)
TYear:今日(年)
day2:Aの経過日(日)
day2 = 365*(TYear - BYear)
これをプログラムとして記述すると次のようになります。実際にプログラムを作成して、実行してみましょう。ファイルの名称は、「day2.c」としておいて下さい。
#include<stdio.h>
void main(void)
{
int BYear,TYear,day2;
printf("BYear = ");
scanf("%d",&BYear);
printf("TYear = ");
scanf("%d",&TYear);
day2
= 365*(TYear - BYear);
printf("day2 = %d\n",day2);
}
このプログラムを実行すると「BYear = 」と画面に表示されますので、自分の誕生日の年を、例えば、「2001」と入力し、「Enter」キーを押します。同様に、今日の日付の年を意味する「TYear = 」についても年を入力し、「Enter」キーを押します。
画面に「day2 = ----」と表示されましたか?「----」には、Aの経過日の計算結果が入ります。
3.@,B1月1日から誕生日,今日までの経過日数
うるう年を無視すると各月の日数は、次のように決まっています。
1月:31日 2月:28日 3月:31日 4月:30日 5月:31日 6月:30日
7月:31日 8月:31日 9月:30日 10月:31日 11月:30日 12月:31日
つまり、誕生日等の前月までの経過日に誕生日等の日にちを加えれば、1月1日からの経過日を求めることができます。これを数式で表すと次のような式となります。
変数
Month:月
Day:日
MDi:月毎の日数
day13:@,Bの経過日(日)
これをプログラムとして表現すると、次のようになります。実際にプログラムを作成して、実行してみましょう。ファイルの名称は、「day13.c」としておいて下さい。
#include<stdio.h>
void main(void)
{
int Month,Day;
int MD[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
int day13;
int i;
printf("Month = ");
scanf("%d",&Month);
printf("Day = ");
scanf("%d",&Day);
day13
= 0;
for(i=1;i<=Month-1;i++){
day13
= day13 + MD[i];
}
day13
= day13 + Day;
printf("day13 = %d\n",day13);
}
4.概算による誕生日からの経過日の計算
うるう年を考慮していないので、概算となりますがプログラム「day2.c」及び「day13.c」を使用することによって、誕生日からの経過日を計算できるようになりました。
自分が生れてから今日まで、いったい何日生きてきたのでしょうか?作成した二つのプログラムを使用して、概算の経過日を計算してみましょう。
5.うるう年の考慮
まずはじめに、うるう年の判定方法について見てみましょう。現在のグレゴリオ暦では、うるう年の決め方は以下の規則によっています。
(1)西暦年数が4で割り切れる年は原則として「うるう年」にする。
(2)上記の例外として、西暦年数が100で割り切れる年は「平年」とする。
(3)さらに例外として、西暦年数が400で割り切れる年は「うるう年」にする。
この規則によると2000年は、「うるう年」でしょうか、それとも「平年」でしょうか?
このうるう年の規則を、年の集合として考えると、4で割り切れる年の集合の中に、100で割り切れる年の集合があり、更にその中に400で割り切れる年の集合があると表現できます(図2を参照)。
従って、「4で割り切れ、かつ100で割り切れない年の集合」と「400で割り切れる年の集合」の合計が、うるう年の集合となります。図2の斜線の部分が、うるう年の集合です。
図2 うるう年の集合
これより、ある年「Year」が、うるう年かどうかを判定するプログラムは、次のようになります。このプログラムを実行すると、うるう年の場合は、「leap =
1」となり、平年の場合は、「leap = 0」となります。
#include<stdio.h>
void main(void)
{
int Year,leap;
printf("Year = ");
scanf("%d",&Year);
leap
= 0;
if(
(Year%4==0)&&(Year%100>0) ) leap = 1;
if(
Year%400==0 ) leap = 1;
printf("leap = %d\n",leap);
}
実際にプログラムを作成して、実行してみましょう。ファイルの名称は、「leap.c」としておいて下さい。1900年、2000年、2004年は、それぞれ「うるう年」なのか「平年」なのか確認しましょう。
以上のように、うるう年を判定するプログラムが完成しました。これをもとに、1980年から2030年までのうるう年を求めるプログラムを下記に示します。
このプログラムを実行して、自分の誕生日から今日までの間のうるう年について調べ、誕生日から今日までの正確な経過日を求めてください。ファイルの名称は、「leap2.c」としておいて下さい。
#include<stdio.h>
void main(void)
{
int Year,leap;
for(Year=1980;Year<=2030;Year++){
leap
= 0;
if(
(Year%4==0)&&(Year%100>0) ) leap = 1;
if(
Year%400==0 ) leap = 1;
if(
leap==1 ) printf("%d\n",Year);
}
}
ちなみに、誕生日を「2001年12月5日」とし、今日の日付を「2004年7月5日」とした場合の経過日は、「943日」となります。
具体的な経過日の計算結果は、次のとおりです。
@誕生日の年における1月1日から誕生日までの経過日数
A誕生日の年の1月1日から当該日(今日)の前年12月31日までの経過日数
B当該日(今日)の年における1月1日からの経過日数
経過日 = A + B - @
@:day13 = 339
誕生日の2001年はうるう年ではありませんので、修正の必要はありません。
A:day2 = 1095
誕生日の2001年から当該日(今日)の前年の2003年までの間にうるう年はありませんので、修正の必要はありません。
B:day13 = 186
当該日(今日)の2004年はうるう年です。そして、7月なので正確な経過日とするためには、+1する必要があります。
経過日 = 1095 + (186+1) − 339 = 943
これで終わりです。
--------------------------------------------
経過日の計算プログラム
--------------------------------------------
#include<stdio.h>
void main()
{
int BYear,BMonth,BDay,FYear,FMonth,FDay,leap;
int monthday[13] =
{0,31,28,31,30,31,30,31,31,30,31,30,31};
int day,day1,day2,day3;
int i;
printf("誕生日:");
scanf("%d%d%d",&BYear,&BMonth,&BDay);
printf("占い日:");
scanf("%d%d%d",&FYear,&FMonth,&FDay);
printf("\n");
/* @ */
day1
= 0;
if(
(!(BYear%4)&&(BYear%100))||!(BYear%400) )
leap=1;
else
leap=0;
for(i=1;i<=BMonth-1;i++){
day1
+= monthday[i];
if(i==2) day1 += leap;
}
day1
+= BDay;
printf("day1=%d\n",day1);
/* A */
day2
= 0;
for(i=BYear;i<=FYear-1;i++){
day2
+= 365;
if(
(!(i%4)&&(i%100))||!(i%400) )
leap=1;
else
leap=0;
day2
+= leap;
}
printf("day2=%d\n",day2);
/* B */
day3
= 0;
if(
(!(FYear%4)&&(FYear%100))||!(FYear%400) )
leap=1;
else
leap=0;
for(i=1;i<=FMonth-1;i++){
day3
+= monthday[i];
if(i==2) day3 += leap;
}
day3
+= FDay;
printf("day3=%d\n",day3);
/* 経過日 */
day
= day2 + day3 - day1;
printf("day=%d\n",day);
}
--------------------------------------------