日暦算の難問です。問題を解きながら、普段私たちが使っている暦の仕組みについて学びましょう。
【算数問題01】閏年は400年間に何回ある?
天文観測によって正確に測った 1 年の長さを太陽年といいます。その長さは
1 太陽年 = 365.2422 日
であることが知られています。現在、私たちの使っているカレンダーはグレゴリオ暦といって、次の規則によって閏(うるう)年を入れて 1 年の長さをできるだけ太陽年に近くなるように調整しています。閏年というのは、他の年の 365 日に比べて日数が 1 日だけ多い年のことです。
① 4 で割り切れる年は閏年とします。
② ただし、100 で割り切れる年は平年とします。
③ ただし、400 で割り切れる年は閏年とします。
③が②より、②が①よりも優先します。たとえば西暦 2000 年は 4, 100, 400 のいずれでも割り切れますが、③の条件を優先的に適用して閏年となります。以上の説明を踏まえて解答してください。
(1) 西暦 1 年から西暦 400 年の間に閏年は何回ありましたか。
(2) グレゴリオ暦の 1 年の長さは平均すると何日でしょう。
(3) グレゴリオ暦における平均の 1 年の長さと 1 太陽年の誤差は何秒ですか。
【ヒント】(3) は「秒数」で答えることに注意してください。
(2) グレゴリオ暦では平年には 365 日、閏年には 366 日あるのですが、これをならして平均を求めてみようという問題です。 (1) の結果により、97 年間は 366 日、303 年間は 365 日です。400 年間の全日数は
\[303\times 365+97\times 366=110595+35502=146097\ 日\]
となります。これを 400 で割ると 1 年当たりの平均日数が求められます。
\[146097\div 400=365.2425\ 日\]
これが答えなのですが、実はもう少し簡単な計算法があります。それは 365 日からの「ずれ」だけを取り集めて、それを 400 等分して各年の日数(365 日)に配ってしまおうという考え方です。つまり 400 年で閏年のずれを全部集めると 97 日ありますから、それを 400 で割ると、
\[97\div 400=0.2425\ 日\]
となります。これを平年の 365 日に配れば、
\[365\div 0.2425=365.2425\ 日\]
という答えが得られます。
(3) 1 太陽年は 365.2422 日ですから、これをグレゴリオ暦の 1 年 365.2425 日から引き算して、
\[365.2425-365.2422=0.0003\ 日\]
となります。これは日数ですから感覚的によくわかりませんね。秒数に変換してみましょう。1 日は 24 時間、 1 時間は 60 分、 1 分は 60 秒ですから、これを次々と掛け合わせると、
\[0.0003\times 24\times 60\times 60=25.92\ 秒\]
という答えが得られます。
【グレゴリオ暦に代わる暦のアイデアを募集します】
1 年で約 26 秒の誤差ですから、グレゴリオ暦はとても優秀ですね。でも「もっと良い方法がないかな?」と色々考えてみることも大切です。私もあれやこれやと考えてみているのですけど、なかなか難しいですね。考え過ぎて頭が疲れてしまったので、皆さんから「新しい暦の案」を募集することにしました。いいアイデアがあったら、下のほうにあるコメント欄からお寄せください。
【VBA】うるう年判定関数
VBA でうるう年を判定する (うるう年なら True, 平年なら False を返す) 関数を作成してみましょう。うるう年であることの条件をそのまま素朴に実装するなら、次のようなコードになるでしょう。
'[VBA] うるう年判定関数 Function LEAP(year As Long) As Boolean Dim x As Boolean x = False '4で割り切れたら判定を真にする If year Mod 4 = 0 Then x = True End If '100で割り切れたら判定を偽にする If year Mod 100 = 0 Then x = False End If '400で割り切れたら判定を真にする If year Mod 400 = 0 Then x = True End If LEAP = x End Function
ブール型変数 x の初期値を False とし、条件を満たす毎に値を変更していきます。シンプルでわかりやすいですが、やや冗長なコードですね。もう少し洗練させたいところです。条件 ② と ③ を先にまとめて処理することを考えます。つまり、100 で割り切れて 400 で割り切れない年は、(条件の優先順位が高いので)平年と決まります。この条件に当てはまらない年のうち、さらに条件 ① を満たす年だけがうるう年となります。ElseIf 構文をうまく使って実装してみましょう。
'[VBA]うるう年判定関数 Function ISLEAP(year As Long) As Boolean Dim x As Boolean If year Mod 100 = 0 And year Mod 400 <> 0 Then ISLEAP = False ElseIf year Mod 4 = 0 Then ISLEAP = True End If End Function
かなり短いコードになりましたね。この関数を使って、西暦 2000 年から 2200 年までのうるう年を並べてみましょう。
'[VBA]うるう年の一覧 Sub LeapYearList() Dim i As Long For i = 2000 To 2200 If LEAP(i) = True Then Debug.Print i; End If Next i End Sub '実行結果 '2000 2004 2008 2012 2016 2020 2024 2028 2032 2036 '2040 2044 2048 2052 2056 2060 2064 2068 2072 2076 '2080 2084 2088 2092 2096 2104 2108 2112 2116 2120 '2124 2128 2132 2136 2140 2144 2148 2152 2156 2160 '2164 2168 2172 2176 2180 2184 2188 2192 2196
実行結果をチェックしてみましょう。2000 年は 400 で割り切れるのでうるう年ですね。2100 年や 2200 年は 400 で割り切れず、100 で割り切れるので平年となっています。
エクセルや数学に関するコメントをお寄せください