Other

暦法

春分の計算・秋分の計算」を書いている時、暦法について考えていた。

グレゴリオ暦は理解しやすく、運用しやすく、精度も充分なすぐれた暦法だと思う。グレゴリオ暦で閏年を決めるルールは3つある。

西暦年を4で割り切れる年は閏年。
ただし、100で割り切れる年は平年。
ただし、400で割り切れる年は閏年。

400年間に97の閏年を設け、1年あたり365.2425日となっているが、それでもまだわずかなズレがあるそうだ。定説では、回帰年は365.2422日なので、3333年間で1日多くなると思う。

1 / (365.2425 - 365.2422) = 3,333.333333333333

既存のルールとの兼ね合いもあるので、おそらく3200年に1日減らすことになるだろう。Wikipediaにも、そんな話が載っていた。1000年も先の話なんてどうでも良いのだが、もうちょっと頑張ろう。そうするとルールがひとつ追加されるかもしれない。

ただし、3200で割り切れる年は平年。

3200年間に775の閏年を設け、1年あたり365.2421875日になる。悪くない。悪くはないが面白くもない。

本題

そこで、私なりに閏年のルールを考えてみた。やっと本題だ。

西暦年を4で割り切れる年は閏年。
ただし、128で割り切れる年は平年。

このルールでは、128年間に31の閏年が設けられ、1年あたり365.2421875日。先ほどと同じ値になる。よく見れば3200は128の25倍、775も31の25倍だ。

定説では、回帰年は365.2422日だが、実はここ100年ほどの間に少し短くなっているようで、Wikipediaによれば、2015年には約365.24218944日だった。回帰年を365.2422日とすれば8万年ぐらい、365.24218944日とすれば51万年ぐらいもつだろうと思う。その頃には、猫の時節になっているかもしれないが。

精度の点ではグレゴリオ暦にルールをひとつ追加するのと変わらないが、ルールが少ないことと、毎年の回帰年とのずれ具合が比較的少ないことは、有利だと思う。

それに、4と128はコンピュータ的には扱いやすい数字だ。4は22、128は27なので、ビット演算をうまく使える。

x年の閏日の日数は、以下の式で求められるようになる。

y = (((1 << 2) - (x & ~(~0 << 2))) >> 2)
    - (((1 << 7) - (x & ~(~0 << 7))) >> 7);

コンパイラになったつもりで、少し整理してみる。

y = ((4 - (x & 3)) >> 2) - ((128 - (x & 127)) >> 7);

0か1を求める式にしては少しややこしいが、条件分岐、三項演算子、乗除や剰余を使わないので、速度的に有利になる。

1年からx年までの閏日の日数を求める式は、もっと簡単だ。

y = (x >> 2) - (x >> 7);

これはすばらしいなと思い、ひとまず満足したが、128の倍数かどうかって、慣れてないので人の感覚では分かりにくいだろう。やはりこの案は難しいだろうか。

未来の100年は果てしなく遠く感じるが、過去の100年は不思議と身近に感じる。

(2016/03/04 初稿)
(2016/03/05 更新)