閏年の定義
グレゴリオ暦法では、次の規則に従って400年間に97回の閏年を設けています。
① 西暦年が4で割り切れる年は(原則として)閏年。
② ただし、西暦年が100で割り切れる年は(原則として)平年。
③ ただし、西暦年が400で割り切れる年は必ず閏年。
この置閏法(閏の挿入規則)によるただし書きをひとことで表すと、「400年に3回、100で割り切れるが400で割り切れない年は、例外で平年とする」ということになります。
これをプログラミング言語で、どのように表現するのが正しいのでしょうか。
閏年の判定アルゴリズム
グレゴリオ暦の閏年は、次のどちらかの判定ロジックで、正しく判定することができます。
計算式①:逐次的な4条件
プログラムで処理しやすくするために、閏年の規則を、次の4条件に読み替える計算方法です。
① 西暦年が400の倍数である場合、閏年
② 条件①を満たさず(西暦年が400の倍数ではなく)、かつ西暦年が100の倍数である場合、平年
③ 条件①と②を両方とも満たさず(西暦年が100の倍数ではなく)、かつ西暦年が4の倍数である場合、閏年
④ 条件①〜③を全て満たさない場合、平年
プログラム言語では、以下のように記述できます。
※注:コーディング例だと、結果が確定した時点でリターンしているため、ELSE内の入れ子を省略する書き方も可能です。コードがもっと短くできますね。
- C言語など
- Visual Basicなど
// C言語など
int year = 西暦;
if (year % 400 == 0) {
return true;
} else {
if (year % 100 == 0) {
return false;
} else {
if (year % 4 == 0) {
return true;
} else {
return false;
}
}
}
' Visual Basicなど
Dim year As Integer = 西暦
If year Mod 400 = 0 Then
Return True
Else
If year Mod 100 = 0 Then
Return False
Else
If year Mod 4 = 0 Then
Return True
Else
Return False
End If
End If
End If
計算式②:1つの論理式
閏年の規則を、次の1つだけの論理式に読み替える計算方法です。
① 西暦年が、「4の倍数である」かつ「100の倍数でない」または「400の倍数である」ならば閏年、そうでなければ平年
この条件は、
①『「4の倍数である」かつ「100の倍数でない」』または「400の倍数である」
②「4の倍数である」かつ『「100の倍数でない」または「400の倍数である」』
の2通りの解釈ができますが、どちらの解釈でも同じ結果となります(「400の倍数である」=「4の倍数である」が成り立つため)。
プログラム言語では、以下のように記述できます。
※注:論理演算子が文字化けするため、当サイトではこの記法を採用しません。が、ひとつの論理式で簡潔にロジックを表現できるため、言語仕様上の制約がなければ、この書き方をするのが一般的かなと思います。
- C言語など
- Visual Basicなど
// C言語など
int year = 西暦;
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
return true;
} else {
return false;
}
' Visual Basicなど
Dim year As Integer = 西暦
If year Mod 4 = 0 And year Mod 100 <> 0 Or year Mod 400 = 0 Then
Return True
Else
Return False
End If
うるう年の確かめ算
西暦を入力すると、①4の倍数か(4で割り切れるか)、②100の倍数か(100で割り切れるか)、③400の倍数か(400で割り切れるか)、をチェックし、うるう年か平年か判定します。
4の倍数 | ○ |
100の倍数 | ○ |
400の倍数 | ○ |
判定 | 閏年 |
ソースコード公開
<form>
<label for="year">西暦<input type="number" id="year" oninput="calc()">年</label>
</form>
<script>
// 計算
function calc() {
let year = document.getElementById('year').value;
let tds = document.getElementsByTagName('td');
// 初期値クリア
for (let i = 1; i < tds.length; i = i + 2) {
tds[i].innerText = '';
}
// 4の倍数
if (year % 4 == 0) {
tds[1].innerText = '○';
}
// 100の倍数
if (year % 100 == 0) {
tds[3].innerText = '○';
}
// 400の倍数
if (year % 400 == 0) {
tds[5].innerText = '○';
}
// 閏年判定
let result = '平年';
if (year % 400 == 0) {
result = '閏年';
} else if (year % 100 != 0) {
if (year % 4 == 0) {
result = '閏年';
}
}
tds[7].innerText = result;
}
</script>
コメント