ラベル 曜日の計算 の投稿を表示しています。 すべての投稿を表示
ラベル 曜日の計算 の投稿を表示しています。 すべての投稿を表示

2025年1月26日日曜日

月齢カレンダー

私がこの数年愛用している予定表の話はこのブログに何回か書いた. ところで, 今年の予定表の表紙にある週日定数も月齢定数も共に0である. つまり下のようなのだ.

そうするとこの次にこうなるのは何年後かも気になる.

y年の週日定数, week(y)と月齢定数, moon(y)は次の式で計算する.

def week(y): return (y-2000+(y-2000)//4 
    +4)%7
def moon(y): return (((y-11)%19)*11)%29
そこで次に(0,0)になる年を計算してみたら, なんと2272年; 247サロス周期の後であった. 今年は昭和100年, 戦後80年, 阪神淡路大震災30年といわれるが, 暦屋にとっても誠に貴重な年なのである.

この表を見た序でに, 今年の復活祭を調べよう. まず3月21日の月齢は21. 次の満月は月齢45として4月14日. その日の曜日は1で月曜だから, 日曜はその6日後で4月20日になる.

もうひとつ序でに. Winning WaysのDoomsdayは3月0日の曜日なので, 今年は5, つまり金曜日である.

2024年7月2日火曜日

Fixed Day Number

前回のブログのアルゴリズムに, 年初から前月末までの総日数を計算する式:
(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が得られる.

どうだろうか.

2024年7月1日月曜日

Fixed Day Number

私の好きな本に, Edward M. ReingoldとNachum DershowitzのCalendrical Caluculation がある. 随分昔に購入したもので, 手元にあるのは2004年のThird Printing.

要するに暦に関するアルゴリズムが満載で面白い. この本では暦の変換の基準は, Fixed Day Numberといい, Gregorian暦が過去に遡って使われたとして, その1年1月1日(の正子)を 第1日とするものである. いちいちfixed day numberといわず, R.D.と いうらしい. (Rata Die)

似たようのものに, -4712年1月1日正午から起算するユリウス日があるが, これは途中でJulian暦 からGregolian暦になるので変換が面倒である.

Calendrical Caluculationにある, Gregorian暦の年月日からそのR.Dを計算する アルゴリズムを見てみよう. 本書のアルゴリズムはCommon Lispで記述されているが, 今日はPythonに翻訳する.
def fixeddaynumber(year, month, day):
    return (365 * (year - 1) + (year - 1) // 4
            - ((year - 1) // 100) + (year - 1) // 400
            + (367 * month - 362) // 12
            + (0 if (month <= 2) else
               (-1 if leap_year (year) else -2))
            + day)
     
最初の365 * (year - 1)は前年までがすべて平年であったとしての, 前年の 最後の日までの総日数である. しかし, 4年に一度閏年があるから, その分を足す. + (year - 1) // 4. Gregorian暦では, 100で整除される年は平年に するのであったからそれを引く. - ((year - 1) // 100). しかし400で 整除されるなら閏年にするからそれを足す. + (year - 1) // 400. 前年末までの総日数はこれで計算出来た.

次は前月末までの日数を計算する. 目標としては, 1月なら0. 2月なら31, 3月は 平年なら59, 閏年なら60, ... 閏年の補正は後でやることにし, 本書にあるアルゴリズム は(367 * month - 362) // 12というものだ. monthを 1から12まで変えてこの値を計算すると:
print(list(map (lambda m:(367*m-362)//12, range(1,13))))
[0, 31, 61, 92, 122, 153, 183, 214, 245, 275, 306, 336]
    
3月からは, 平年なら2, 閏年なら1多いことがわかる. 従ってこの関数の month番目を使い, monthが1, 2ならこの値そのまま, 3以降はこの値から 平年は2, 閏年は1を引いて使う.

これで前年末までと前月末までの総日数が分ったから, 後はdayを足せばよい.

閏年の補正に本書ではこういう式を使う.
def leap_year (year):
    return (year % 4) == 0 & ((year % 400)
                              in [100, 200, 300])
    
これで1年1月1日を計算すると:
print (fixeddaynumber (1, 1, 1))
1
 
なるほど. また, おととし, 開業150年と話題になった鉄道開通の日, 1872年10月14日(明治5年には日本は まだ旧暦を使っていたが, これは太陽暦に換算してある)のR.D.を計算してみる.

各々の項の値は682915, 467, -18, 4, 275, -1, 14で, R.D.は683656 である.

ところで私は何度も暦の計算のプログラムを書いたが, その年の終までの日数を計算し, その月の前までの日数を引いて日を足すのが好きだ. 上のアルゴリズムに year - 1が4回もあるのが気に食わないのである.

それで普通は年末から今月0日までの日数を引くことになるが, 大体はそこは定数の 表を利用する. しかし, Calendricalの本にあるような式が使えないかと 考えた. Calendricalの式と同様, 1,2月は特別扱いにしてもよいとして, 定数など を変えてテストした. 欲しい値は:
[[365, 366], [334, 335], 306, 275, 245, 214,
 184, 153, 122, 92, 61, 31]
    
である. 左端が1月と2月で, かっこ内は左が平年, 右が閏年. 右端が12月. その結果, (4777 - 367 * m) // 12がよいらしかった. つまり
print(list(map (lambda m:(4777 - 367 * m) // 12,
                range(1,13))))
[367, 336, 306, 275, 245, 214, 184, 153, 122, 92, 61, 31]
    
1月, 2月は平年は2を引き, 閏年は1を引く.

ここで使う定数4777は非常にクリティカルで, 4776や 4778に変えてみると, 前者は7月が小さく, 後者は2月が大きい.
print(list(map (lambda m:(4776 - 367 * m) // 12,
                range(1,13))))
[367, 336, 306, 275, 245, 214, 183, 153, 122, 92, 61, 31]

print(list(map (lambda m:(4778 - 367 * m) // 12, 
                range(1,13))))
[367, 337, 306, 275, 245, 214, 184, 153, 122, 92, 61, 31]

これを利用して書いたfixed day number関数は次の通り:
def fixeddaynumber2(year, month, day):
    return (365 * year + year // 4 - (year // 100)
            + year // 400 - (4777 - 367 * month) // 12
            + (0 if (month > 2) else
               (-1 (year % 400 == 0)
                if (year % 100 == 0) else
                (year % 4 == 0) -2))
            + day)
こちらで鉄道記念日を計算したのと, 本年6月30日の値の7で割った剰余とを見ると:
print (fixeddaynumber2 (1872, 10, 14))
683656

print ((fixeddaynumber2 (2024, 6, 30)) % 7)
0       
だから, R.D.を7で割った剰余が曜日になるわけだ. つまり, R.D.1の日, 1年1月1日は月曜であった.

年末から月始めまでの日数を今回のように式で計算すると, 実引数に0月とか13月が与え られても計算してしまう恐れがある. 表なら範囲外としてエラーに出来る. それを 心配したとしても, 日の値に範囲外が与えられる可能性はあるのだから, まぁ我慢することに しよう.

2016年1月25日月曜日

曜日の計算

久し振りに曜日の計算の話だ. 2011年5月25日の私のブログ(曜日の計算)に

「21世紀中の 2000+y年m月d日の曜日は, (y+floor(y/4)+h(m)+d+4) mod 7 を計算するとそれが曜日になる.」

ただし「うるう年の1月と2月はh(m)の値から1を引く必要がある.」

とあり,
m 1月 2月 3月 4月 5月 6月 7月 8月 9月10月11月12月
h   2   5   5   8   3   6   1   4   7   2   5   0
の表がある.

今日の話題は上の式の「+4」と直ぐ上のh(m)である. 21世紀は+4だと書いたが, では他の世紀ではどうなるか. 20世紀に当て嵌めて計算してみると, その時代には+5であった.

我々の生きている20, 21世紀中は, この+5と+4を覚えておけばいいが, もう少し一般的に出来ないかと考えてみた. グレゴリオ暦は4世紀で曜日が元に戻るから, 年を100で割った整数部をさらに4で割った剰余に対してこの値を決めればよいわけだ.

1900年からは(剰余が3で)+5
2000年からは(剰余が0で)+4
もっとやってみると
2100年からは(剰余が1で)+2
2200年からは(剰余が2で)+0
だから, この剰余の0,1,2,3に対応して +4,+2, 0,-2と覚えておけばよいことが分った.

剰余  0  1  2  3
b    +4 +2  0 -2
上の式は (y+floor(y/4)+h(m)+d+b(c)) mod 7 になる.

h(m)の表は, 1月の2, 2月の5は覚えるとして, 後は奇数の月も偶数の月も5回ずつあり, 偶数月は12-m, 奇数月は3,5,7月は8-m, 9,11月は16-mと覚えるのがよさそうだとこの頃は思っている.

使ってみよう. グレゴリオ暦に改暦された1582年10月15日の曜日は (82+20+2+15-2) mod 7=117 mod 7=5 だから金曜. 日本でグレゴリオ暦に改暦された1873年1月1日の曜日は (73+18+2+1+0) mod 7=94 mod 7=3 だから水曜であった.

2014年8月2日土曜日

曜日の計算

数学セミナー1978年7月号に島内剛一先生が寄稿した「万年七曜表」に登場する計算尺については, すでに2回のブログで説明した.

今回は円形計算尺によるものを話題としたい. 私はこれが一番好きだ.

前回の円筒式のものを見れば, そのまま円形にもなりそうに思うが, 島内方式の円形計算尺は, また趣向が違って, 次のような形をしている. 島内流にいうと上からA,B,Cである. (私の流儀で書き直しているから数セミの図とは多少違う.)







これらを重ねるのでA,B,Cをそれぞれ黒, 青, 赤の各色で示す. A, B, Cは紙に書き込まれ, 共通の中心の回りに回転出来る. Aには時計でいえば1時方向, 3時方向, ..., 11時方向には, Cにある月名を見る穴が開いている. (島内式では5時と7時方向にしかない. 紙方式ではAとCの間にBがあるので, Bにも同じ半径で5時方向から7時方向までの円弧状の穴がある.)

Aの黒文字は西暦の上2桁で, 外周の0から15がユリウス暦, 内周の15から22がグレゴリオ暦だ. Bの青文字は外の一周が日付, 内側の3周は西暦の下2桁. Cの赤文字は, 外が週日, 内側が月名である. 週日のRは木曜のこと.

前回と同様, まず2014年7月について, これを使ってみるには, まず11時方向の黒の上2桁(20)と7時方向の青の下2桁(14)を合わせる. 下の図は黒はそのままで青を右方向に4時間分ほど回転している.



黒と青をそのように合せてから, 外側の赤の紙を, 週日名と日付が合わさるように回転し, 黒の月名用のどれかの穴から目的の月名が見えるようにする. この図では9時方向の穴に赤字の7が見える. 週日名は円周に沿って6回繰り返すので, 月名は6個の穴のどれで見えてもかまわない. このように回転すると7月1日が火曜なのが分る.

ところで, その穴で7が端の方のあるのは, ここで丸めているからで, 赤字の紙は青字の日付と赤字の曜日が重さなるように, 離散的に動かすから, このようになる.

5時方向の穴に4が見えるのは, 4月と7月は曜日の関係が同じだからだ.

再び前回同様に2000年1月について試みると



のよう黒の20と青の00が重さなり, 11時方向の枠に1が入り, 1日の相方に土曜の方のSが來るので, 1月1日は土曜であった.

例によってこの仕掛の説明である. 2014年7月の計算法について, mod 7の図を示すと次のようだ.



2014の上2桁は20なので, 黒の目盛のf(20)=5.875にマークする. 下2桁14ではg(14)=17なので, mod7をとり, 青の3にマークし, これらを合せる.

青は1.875分右に移動する. 今は赤も青と一緒に移動する.

このとき赤のb(7)=13.25は黒の目盛上では赤点の1.125に対応し, これを丸めると1になる. 従って7月0日は月曜だ.

5.875+17+13.25=36.125=1.125 mod 7

2000年1月で試みると



5.875+(-0.25)+6.75=12.375=5.375 これが黒目盛上の赤点の位置で, これを丸めて1月0日は金曜である.

調べようとする年月の0日の曜日までは分ったが, これをカレンダーに対応させるにはまたひと工夫がいる.

とりあえず青に下の図のように, 1,2,...,7を書き入れる. これが日付だ. また赤にも図のように曜日を書き込む. そして赤目盛を動かす.

また黒目盛の0(mod 7だから7も)の両側に0.5の幅をとり(つまりこの範囲を丸めると0になる), 赤目盛上の月の値の黒マークがその範囲に入るように, 青と目盛の位置を合わせながら移動するのである.

2014年7月で使ったふたつ上の図の赤目盛は一目盛分左にずれて, マークが7付近に近づき, 青の1日が赤の火曜に対応する.



2000年1月での図もこのようになる.



要するに日付と曜日はなんとなく書き入れておき, 赤目盛の黒点を黒目盛のどの値の範囲に置くと曜日と日付が対応するか試み, その範囲が0付近になるように日付を再調整したまでである.

なかなか楽しい島内方式の検討であった.

私は例によってPostScriptを活用したが, 島内さんは「円周を42等分するには, まずコンパスで6等分し, それをさらにコンパスまたはディバイダで7等分するのがよいだろう.」と書いているから, そのようにして作図していたのかもしれない.

いまやこの計算尺を作るにも文明の利器が出現してきているが, 一方計算尺がなくても曜日が簡単に分かる手段も増えていて, 計算尺の出番もない.

2014年7月23日水曜日

曜日の計算

前回のブログで島内先生の計算尺方式の万年七曜表を話題とした.

余談ながら現在東京理科大学の近代科学資料館で開催中の企画展「計算する器械たち---アナログコンピュータ展」には 円筒形の計算尺も展示されている. 今回はそういう円筒方式の万年七曜表の話だ.

下の図を見てほしい. ちょっと分り難いがこれが円筒式のもの(展開図ともいうべきもの)だ.



前回のブログを見た人なら思い出すだろうが, 最上段の右から0,1,...,15 少しあけて15,16,...,20とあるのは西暦の上2桁である. 右側の15まではユリウス暦, 左側の15からはグレゴリオ暦用のものだ.

その下, 5段位に左下がりに並ぶのは西暦の下2桁である. 段々と下るのは円筒の卷いたとき, 21に22を自然に繋げるためである. なかなか凝っている(次の図を見ると分る). 44は丁度切れ目になってしまった.

次は2, 8, 5,...と現れて, 4と7が重さなっているから, これは月名である. 展開図の範囲に4回出てくる.

最後は, 今度は右下がりだが, これは一箇月のカレンダーである.

もうひとつ青色の枠の図がある. 週日名が書いてあるほか. 枠の所が3カ所くり抜いてある.

島内さんの記事では, 西暦上2桁と月名が1枚の紙でCといい, 下2桁とカレンダーがもう1枚の紙でBといい, 青色の枠の紙はAである. 同じ幅に描いてあるが, A,B,Cの順の幅がすこしずつ短くなり, Aが一番外側, Bが真中. Cが内側でそれぞれ円筒状になって外中内の順で差し込まれている.

勿論底の場所は同じで, 展開図では左右に移動するように, 円筒は回転できる.

前回の例と同様に2014年7月の曜日を見るには,



のようにCの20の真下にBの14を合せる. そしてCの7月がAの月名を入れる青色の小さい枠に入るように合せると, 図のように青色の大きい枠がカレンダー部分に重さなり, 7月1日が火曜と判明するのである.

この図では, Bの紙が円筒になっているのが見えるであろう.

難しいのは例の丸めのところである. この図でも青色枠内の4と7が枠の左右の中央にないのが見てとれる. 4と7の中央は1.125という位置にあり, 枠の中央が1なのである. どこか中央かは, 下のカレンダー部分の枠の左右がカレンダーの数字の丁度真中に來るように離散的に合せることで分るのだ.

もうひとつの例



この例は2000年1月で, 閏年であり, 1月, 4月, 7月が同じ曜日の配置になる(Aの同じ枠に入る)ことが見てとれる.

さてこの計算尺の仕掛けの説明だが, mod 7の範囲だけの図にしたのが次だ.



最上段の線が西暦の上, その下の線が西暦の下で, 2014年になるようにその20と14を対応させた図になっている. つまりBの紙が右に移動している. (輪だから左かもしれない.) 移動していることを示すため赤で描いてある.

その下の線が月名で, これは最上段と同じ紙, 同じ位置にある.

さて赤の線の基準に対して7月の位置を計算すると, g(14)とf(20)が合っているから, 黒の基準位置はg(14)-f(20). 従って7月の位置はg(14)-f(20)+b(7). ところがfのスケールは反対に取ってあるから, g(14)+f(20)+b(7)になって, 実際の値を入れると
17+5.875+6.25=29.125=1.125 mod 7
従ってこれを丸め, 7月0日の値が1. すなわち7月1日は2(火曜)となる.

7月のすぐ右に9月がある. だから9月0日の値は0, 9月1日は1(月曜)だ.

従って青色の枠は下のように作ればよい.



上の小さい枠に7月があると, その1日は火曜. 上の枠がひとつ右に移ると, 曜日の名前が右にひとつずれて, 9月1日が月曜になるという仕掛である.

2014年7月14日月曜日

曜日の計算

私が2011年5月25日や6月5日のブログに書いた故島内剛一(しまうちたかかず)先生の曜日の計算は興味深いものであった. 先生の数学セミナーの記事(1978年7月号)には驚くようなアルゴリズムが沢山登場する.

その中で, しばらく私が読み飛ばしてはいたものの, 気になっていたのは, 「計算尺方式の万年七曜表」であった.

先日来, ちょっと読み直してみたが, もとの図を島内さんがどのようにして書いたか不明である. 雑誌に掲載された図の正確さもよく分らないので, 使い方が分かった時に, 自分で図を書き直してみた. (元の記事には「日のひと目盛の1/8=0.125までの精度はどうしても必要」と書いてある.)

ざっといえば, 下のようなものである.



上下2枚の図があり, どちらも半分が上下逆になっているのは, 中央で折って表と裏にするのである. 島内さんは上をB, 下をCといった.

Bの上半分は横に2倍にしたカレンダーである. 左側のどの列から始めても一週間分があるようになっている. 下半分は西暦の下2桁の表だ. こちらもかなり冗長である.

Cの下半分は月名である. 左の方, 3と11が縦に書いてあるのは, 3月と11月の曜日が同じことをしめす.

上半分は西暦の上2桁になっている. 0から15までの部分と15から22までの部分があるが, 前者はユリウス暦, 後者はグレゴリオ暦に対応する.

私は島内さんの記事のこれらの図をコピーし, 切り抜き, BとCを計算尺のように滑らせながら操作してみて, 使い方が分ってきた.

逆さまの図は見にくいから, 正立させた図にしよう. 上下の余白も省いた.



この上の図では上と下が表面と裏面に相当する. それぞれの面の途中の横線が計算尺の滑る位置だ. 上のカレンダーの中央付近に緑色の枠が見えるのは, 通常の計算尺にあるカーソルのようなもので, その内部がその年その月のカレンダーになる.

前の説明の繰り返しだが, 上から月, 日, 年の下2桁, 年の上2桁である.

さて, 2014年7月のカレンダーを見るには下の図のようにする.



下の西暦上2桁の20と, 上の西暦下2桁の14が合うように下の目盛を右にずらす. すると上の月名の目盛は(上下反転したので)同じ長さだけ左にずれる.

日の表の上端に曜日の区間の境界を示す青い線があり, 7の下の対応する区間の中央にM(monthのつもり)がくるように緑の枠を滑らすと, 7月1日が火曜になり, 7月のカレンダーが得られる仕掛けである.

目盛合わせが正確にできるよう, この図には多くの縦線が引いてある. ユリウス暦とグレゴリオ暦の間には微妙な差があるので, グレゴリオ暦の部分は青線で表示する.

この計算尺でカレンダーが出来る魔法のような理由は次のとおり.

式が導出された経過は省略するが, 島内方式で西暦y年m月d日の曜日は

round(f(y idiv 100) + g (y % 100) + b (m) + d) % 7

で計算する.

y idiv 100は西暦の上2桁. y % 100は下2桁である.

f(y)= - floor(3(y+1)/4) - y + 6 + (y % 4 == 0 ? -0.125 : +0.125)
(ユリウス暦に対するfの式は省略)
g(y)= y==0? -0.25 : (y + floor (a/4) - y % 4 ==0 ? -0.5 : 0)
bは1月から12月について
6.75, 2.75, 3.25, 6.25, 1.25, 4.25, 6.25, 2.25, 5.25, 0.25, 3.25, 5.25
である.

y=15から22までのfの値は
0.125, 5.875, 4.125, 2.125, 0.125, 5.875, 4.125, 2.125

y=0から15までのgの値は
-0.25, 1, 2, 3, 4.5, 6, 7, 8, 9.5, 11, 12, 13, 14.5, 16, 17, 18

アルゴリズムを解明すべく, これを次のような目盛に記入する. gは7の法をとってある. 目盛を下からf, g, m, dということにする. dの線の上の1〜7はカレンダーの一番上の数である.



いま2014年の計算をしようとして, 下の図のようにfの目盛の20とgの目盛の14を合わせると(赤い線), gの0はfの1.875に合う.

これはf(20)=5.875, g(14)=3の和 5.875+3=8.875=1.875(mod 7) である.



通常の計算尺でA尺とB尺を使い, log x + log y を計算するには, A尺のlog xのところにB尺の1(原点)を合わせ, B尺のlog yに対応するA尺を見るとlog x + log yになっている.

しかし今の計算では, gの目盛が逆向きにとってあるので, 通常の計算尺の減算の要領で加算が出来るようになっている. 結局fが右に1.875ずれているわけで, 同時に一番上のmも左1.875(=f+g)ずれている. mでの7月のb=6.25に対応するdの位置(緑の線)は, f+g+bの値f(20)=5.875, g(14)=3, b(7)=6.25の7を法とした和1.125)になっており, 丸めると1になる.

7月はこの値が1. ということは1日はd=1を足すから2になって火曜になる. 従ってカレンダーの中央の水曜を2日の上に置くことになる. dの値の1の上に2とある理由だ. 丸めた値が2だと1日は3だから水曜で, カレンダーの中央を1日に置く. dの目盛のカレンダーの値はそのように決めてある.

この説明も回りくどいが, 実は私も理解に到達するのに結構苦労した. 島内さんの発想に驚くばかりである.

2012年6月14日木曜日

曜日の計算

2012年6月13日の私のブログ「復活祭公式」にある, Winning Waysが「3月28日 Doomsday(最後の審判の日)」という日の曜日は実はなかなか重要である.

曜日としては3月28日は3月0日と同じだが, この曜日は4月4日, 6月6日, 8月8日, 10月10日, 12月12日の曜日と一致する. (これらを目印の日といおう.) 4月から後については, 偶数4≤m≤10のm月m日と(m+2)月(m+2)日の間隔は, 大の月が1回と小の月が1回と2日あるから31+30+2=63で, これが7で整除出来るから同じなわけだ.

5月以降の奇数月については, 大の月m∈{5,7}ではm月(m+4)日, 小の月m∈{9,11}ではm月(m-4)日が同じ曜日になる. つまり大の月のm月m日と次の(m+1)月(m+1)日の間隔は31+1=32日, 従ってm月(m+4)日から後の目印の日までの間隔は4日減って28日になる. 小の月のm月m日と(m+1)月(m+1)日の間隔は30+1=31日, m月(m-4)日から後の目印の日までの間隔は4日増えて35日になり, どちらも7で整除できる.  ブラボー!

このように4を足したり引いたりするより, 4ヶ月離れた5月9日と9月5日, 7月11日と11月7日が目印の日と私は覚えているが, 次のパラグラフの1月のことを考えると+4日という情報は覚えておく価値がある.

さてその4月より前の月はどうか. 3月は最初に書いたように0日が目印の日だ. 3月が31日あり, 4月4日までは35日あるから確かに. もちろん3月は大の月だから, 3月(3+4)日が目印の日になる, 1月と2月については前年の13月と14月と思えはよいが, 14月14日は途中に大の月が2回あるから, 上の偶数月とは同じ関係にはならない. が, 上記のような理由を理解していれば2月は14-1=13日が前年の目印の曜日になる. また1月は大の月だから13-1+4と1月16日になる.

昨年の目印の曜日は月曜であった. 今年のカレンダーを見直すと, 1月16日, 2月13日は, 月曜で当たりだ. 今年は来年の2月まで水曜, 水曜と唱えていれば, 各月の曜日の計算はお茶の子である.

2011年6月5日日曜日

曜日の計算

5月25日の私のブログにある2番目のh(m)の表は

m 1月 2月 3月 4月 5月 6月 7月 8月 9月10月11月12月
h 2 5 5 8 3 6 1 4 7 2 5 0

となっており, 1月2月は別として, 3月以降は奇数月の値は奇数, 偶数月に値は偶数になっていて, 一見美しい. だが待てよ. 大小の月は, 大体交互だが, 7, 8月と大の月が並ぶ. さてはこの表は間違っているかと一瞬疑った.

ある月が小の月, 30日だと次の月は 30 mod 7=2だから, 2だけ増え, 大の月, 31日だと31 mod 7=3だけ増えるはずである. そうすると小の月の後では偶奇は変らず, 大の月の後では変るはずである. しかし, 奇数の除数7で mod 7を取っているので, 商が1増えた時, 今の関係は反対になるわけだ.

3月を5, 4月を8にしたことが, 効いているかも知れないが, どこで商が増えるかにも注意して, もう一度きちんと計算してみたい.

その結果が次の表である. Aの行は月, Bの行はその大小. Cは3月を5として, 大の月には3, 小の月には2を足したものである. ところどころの赤の縦線は, 7のmodを取ると, その前で商が1増えることを示す. DはCの偶奇を示す.



さて, 前回述べたように, 7のmodをとるについて, 4月の1は8に, 9月の0は7にした. 従って, Eの行に示すような値になり, 商が増える場所を赤の長い縦線で示す. FはEの偶奇である.

この赤線で囲まれた区間は, 交互にDの偶奇と同じ, 反対を繰り返す. つまり3, 4月はDとFは同じ, 5, 6月は反対, 7, 8, 9月は同じ, 10, 11月は反対, 12月は同じである. この区間の境界は, Dの行で, 偶偶, 奇奇と並んでいる間にある. 従って, Fの行では偶奇が交互に現れるのであった.

要は4月を8, 9月を7にして, 商の増えるのを1ヶ月遅らせたところに, 仕掛けがあったのだ.

こう検討してみると, あの表はいよいよ忘れ難くなるわけだ.

2011年5月25日水曜日

曜日の計算

1989年12月19日に59歳で他界された基礎論の数学者, 島内剛一(しまうち たかかず)先生を知る人はもう少ないに違いない. 私はプログラミング言語の設計などで, 島内さんには多くの影響を受けた. 基礎論の専門家だけあって, 計算機の見方も一種独特であり, 島内マニュアルは「計算機は順序のあるビットの有限集合である.」のように書き始める.

島内さんの多くの特技の1つが, 曜日の計算であった. 年月日をいうと10秒くらいで何曜と返ってくる.

その秘法は何か. 私の推測では, 島内さんは,

m 1月 2月 3月 4月 5月 6月 7月 8月 9月10月11月12月
h 2 5 5 1 3 6 1 4 0 2 5 0

のような, 月始めの曜日の表h(m)だけを記憶していたらしい.

すると, 21世紀中の 2000+y年m月d日の曜日は, y+floor(y/4)+h(m)+d+4 mod 7 を計算するとそれが曜日になる.

やってみよう. 2011年5月25日の曜日は, 11+floor(11/4)+h(5)+25+4 = 13+3+25+4 = 45, 45 mod 7 = 3 すなわち水曜である.

だれもが知っているように, 平年ならある日の曜日は, 365 mod 7 = 1 ゆえ, 翌年は次の曜日になる. うるう日をまたぐと, 2日増える. これがyとfloor(y/4)を足す理由である.

うるう年は1月2月も2増やしてしまったが, これでは駄目なので, うるう年の1月と2月はh(m)の値から1を引く必要がある.

最後の+4は21世紀中に通用する定数で, 曜日を合わせるためのものだ. そもそもh(m)の表は全体を一斉に増やしても減らしても問題ない. 補正値をそれに応じて変えるだけである.

要はh(m)の表を覚えやすく作ることだ. 島内さんは似たような表を, おそらく無理に覚えてしまったのだろうが, 私は上の表を工夫をして書いた. mod 7を取るのだから, 7を足しても意味は変らないので, 4月を8に, 9月を7にする.

m 1月 2月 3月 4月 5月 6月 7月 8月 9月10月11月12月
h 2 5 5 8 3 6 1 4 7 2 5 0

この表で, 4月から始まる偶数の月の値は, 8, 6, 4, 2, 0である. 一方, 3月から始まる7月までの奇数の月の値は, 5, 3, 1で, その先は負になるから, 心機一転9月は7に, 11月は5にするのである.

残りは, 経験で知っているように, 2月は3月と同じ, 1月は10月と同じと覚える.

3月は5で, 4月は8の出発の値の記憶が肝心である(9月の7も?). そして2か月で2ずつ減る(2か月の間に, 通常は30日の月と31日の月があり, 30+31=61=-2 mod 7だからだ). それと世紀の定数の+4を忘れないこと.

練習問題
2000年1月1日は何曜か. (うるう年に注意)
9.11の2001年9月11日は何曜か.
来年日本で金環食が見られる2012年5月21日は何曜か.
unix timeの31ビットが立つ, 2038年1月19日は何曜か.

今年ももう年の半ばまで来た. 今年中は, 11+floor(11/4)+4=17 そのmod 7は3だから, 3+h(m)+d mod 7で計算する.

曜日に計算では, 無理に誤差をいれる島内の方法や, John Conwayの方法などが面白いが, それらはまたいずれ.

2011年5月23日月曜日

曜日の計算

森本雅樹君の追悼文集, 「森本さんの宇宙」の最後の年表「森本おじさんの足跡」に「1932年5月14日(何曜かわかりますか) 東京に生まれました」と書いてある. よし, 計算しよう.

その頃の日付と曜日の組で分かっているのは, 1941年12月8日が月曜ということだ. 太平洋戦争開戦の日を私は記憶している. その日, 学校に行ったという他は曜日は怪しい(月曜だったらしいというかすかな記憶はあるが). 一方, ハワイの軍港は, 12月7日の日曜で, 軍艦にいない水兵が多かったという話から, 12月8日は確かに月曜であったろう. その前, 数年の12月8日の曜日を書いてみると,

1941
   40 日 うるう年
   39
   38
   37
   36 火 うるう年
   35
   34
   33
   32

従って, 1932年12月8日は木曜だ. 12月12日と5月9日の曜日は同じだから, 5月14日曜日は木曜の4日後の5日後だから, 土曜か.

そこで, 手元のHHC電卓で確認する. 1932年5月14日を19320514と入力し, JDを押すと2426842. それに1を足して7で割る. 商は346691. 剰余は6. たしかに土曜であった.

ついでに,... 手元にMacBookもあるから, 道具がますます高級になり,

% cal 5 1932
May 1932
S M Tu W Th F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31