1
0

More than 1 year has passed since last update.

うるう年計算の疑問

Last updated at Posted at 2023-07-30

うるう年(閏年)とは

うるう年(閏年)は1年が366日ある年です。そうでない年は平年です。

グレゴリオ暦によるルール

  1. 西暦年が4で割り切れる年は(原則として)閏年。
  2. ただし、西暦年が100で割り切れる年は(原則として)平年。
  3. ただし、西暦年が400で割り切れる年は必ず閏年。

うるう年を計算する関数について

Pythonのcalendarモジュールのisleap()関数は、下記のように定義されています。

def isleap(year):
    """Return True for leap years, False for non-leap years."""
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

さて、ここで2つの疑問がわきました。

  • なぜ、ルールはわかりにくく例外を重ねる書き方をしているのか?
  • なぜ、Pythonのコードはルールの順番通りに書いてあるのか?

それぞれ考察してみましょう。

なぜ、ルールはわかりにくく例外を重ねる書き方をしているのか?

ルールの英語の記述は、下記のようです。

Gregorian leap year rule is: Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400.

例外を重ねる書き方は、この訳と思われます。
また、このルールの順番は、暦年の平均の長さの精度を高めていく順番と思われます。

  • 暦年の平均の長さ ≒ 365.24218944日
  • ルールの1まで:365.25日
  • ルールの2まで:365.24日
  • ルールの3まで:365.2425日

また、この順番は可能性の高い順と見ることもできます。

なぜ、Pythonのコードはルールの順番通りに書いてあるのか?

Pythonのandorは、短絡評価されます。短絡評価とは、下記のことです。

  • 式1 and 式2で、式1の判定がであれば式2を評価しない。
  • 式1 or 式2で、式1の判定がであれば式2を評価しない。

判定する年に偏りがないものと仮定すると、短絡評価により下記が最も効率のよい書き方になります。

year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

理由を説明します。
3/4は確実に平年です。したがって、year % 4 == 0が偽かどうかを見ることで3/4は1回の評価で済みます。
残りの1/4を考えます。このとき24/25は確実にうるう年です。したがって、year % 100 != 0が真かどうかを見ることで全体の24/100は2回の評価で済みます。
残りの1/100は3回の評価で決定します。
つまり、可能性の高い順に評価することで、短絡評価により効率的になります。

具体的に2000年から2399年までで確かめると、下記のように評価回数が最小になっています。

評価回数
year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 504
year % 4 == 0 and (year % 400 == 0 or year % 100 != 0) 599
(year % 100 != 0 or year % 400 == 0) and year % 4 == 0 801
(year % 400 == 0 or year % 100 != 0) and year % 4 == 0 1196
year % 4 == 0 and year % 100 != 0 or year % 400 == 0 804 ※

※ ちなみに、表の最後のように括弧がなくても(今回は)ルール通りですが、効率的ではありません。

2つの疑問を考えることで、ルールとコードに共通する理由が見えてきました。

以上

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0