(367 * month - 362) // 12があった. monthを1から12まで変えて値を計算すると.
[0, 31, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336]が得られる. 演算子「//」で小数点以下を落しているが, その落された値を調べると, ( (4777 - 367 * month) // 12 の図も右に示す.)
のような図になる. どちらも2月は30日あるとする.
まず左の図に注目する. 1月から2月は下がり, 2月から3月は上がり, 4月へは下がり, ... 8月と9月へは下がり, ... つまり大の月の後は下がり, 小の月の後は上がるらしい.
計算して見ると下がる量は0.4167, 上がる量は0.5833である.
もう一度式を見ると, monthが1増えると, 367 / 12 つまり 30.5833 増える. これと30及び31の差であった. これで納得できるが, Calendrical Calculation にはこういう説明があった.
(7 * m - 2) // 12 + 30 * (m - 1)この第2項 30 * (m - 1) はすべて小の月として前月末までの総日数.
第1項はm = 1, 2, ..., 12について,
0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 6, 6 31 30 31 30 31 30 31 31 30 31 30である(上の行), 下の行は1月から11月までの日数で, こうして見ると, 大の月の 上で上の行の値は1増える. つまり小の月とした時の誤差を得ている.
そこで上の第1項と第2項を足すと, (367 * m - 362) // 12になるのであった.
2月を30日にしたという発想がよかったのだ. 一方, 年末から計算する方の式はこう導く.
欲しい値は1月, 2月, ..., 12月で, 2月も30日とするから
[367, 336, 306, 275, 245, 214, 184, 153, 122, 92, 61, 31]である. 30の倍数の列
[360, 330, 300, 270, 240, 210, 180, 150, 120, 90, 60, 30]に誤差の列
[7, 6, 6, 5, 5, 4, 4, 3, 2, 2, 1, 1]を足したものだ. これは7から年初からの計算の誤差を引いたのもだ. つまり,
7-(7 * m - 2) // 12
でこれを(13 - m) * 30 に足す. これを一纏めにしたい.
まず下の計算の1行目のように, 床関数を天井関数にする. そして1を足して床関数に戻す. しかしmの値によっては, 整数になることがあり, 1を足すと失敗する. 従って, 2行目のように, 1の代りに 11/12を足してみる. 3行目はそれに30日の倍数を足したところ. 最後に分数の外に ある部分を分子に足す. すると(4777-367m)//12が得られる.
どうだろうか.



0 件のコメント:
コメントを投稿