坂本のアルゴリズムを使用して、特定の日付から曜日を見つけています。誰かがこのアルゴリズムの正確さを教えてもらえますか?私は2000年から2099年までこれが欲しいだけです。
Wikipedia のアルゴリズムが参照用に提供されています。
int dow(int y, int m, int d)
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
t[]
配列が正しいと仮定すると、12個のスポットチェックで確認できます(月ごとに任意の日/年を使用して確認できます)。
y -= m < 3
は素晴らしいトリックです。 3月1日に始まり、2月28日(または29日)に終了する「仮想年」を作成し、その年のendに余分な日(ある場合)を入れます。というか、前年年の終わりに。たとえば、2011年の仮想年は3月1日に始まり、2月29日に終了し、2012年の仮想年は3月1日に始まり、次の2月28に終了します。
うるう年の追加日を仮想年の終わりに置くことにより、残りの表現が大幅に簡素化されます。
合計を見てみましょう:
(y + y/4 - y/100 + y/400 + t[m-1] + d) % 7
通常の年には365日あります。 52週間と1日です。したがって、一般的に、曜日は1年に1日シフトします。それがy
用語の貢献です。年ごとに1日に1が加算されます。
しかし、4年ごとはle年です。それらは4年ごとに1日余分に貢献します。仮想年を使用することで、合計にy/4
を追加して、y
年でうるう日がいくつあるかをカウントできます。 (この式は整数除算の丸めdownを想定していることに注意してください。)
しかし、100年ごとはうるう年ではないため、それはまったく正しくありません。したがって、y/100
を減算する必要があります。
ただし、400年ごとが再びうるう年であることを除きます。したがって、y/400
を追加する必要があります。
最後に、月の日d
と月に依存するテーブルからのオフセットを追加します(年内の月の境界はかなりarbitrary意的であるため)。
それから週7の長さなので、mod 7を全部使いましょう。
(たとえば、週が8日間の場合、この式で何が変わるのでしょうか?さて、mod 8です。当然、y
は5*y
である必要があります。なぜなら、365%8 = = 5.また、月のテーブルt[]
を調整する必要があります。それだけです。)
ちなみに、カレンダーが「9999までは良い」というウィキペディアの声明は完全にarbitrary意的です。この式は、10年、100年、1000年、100万年のいずれであっても、 グレゴリオ暦 に固執している限り有効です。
[編集]
上記の議論は本質的に帰納法による証明です。つまり、特定の(y、m、d)に対して式が機能すると仮定すると、あなたはそれが機能することを証明する y + 1、m、d)および(y、m、d + 1)。 (yは3月1日から始まる「仮想年」です)ですから、重要な質問は、ある年から次の年に移動すると、合計額は正しい量だけ変化するのでしょうか?うるう年の規則を知っていて、年末に余分な日がある「仮想年」では、ささいなことをします。
最近、私はこのアルゴリズムについてのブログ投稿を書きました here 。
アルゴリズムの背後にある基本的な考え方は、2月と1月に前の年の12月31日から曜日をカウントすることです。他のすべての月については、current year 31 Decから曜日をカウントします。最初に2つのステップでこれを行い、現在の月の前の月の最終日の曜日を計算しますm
7を法としてd
を追加します。
31 Dec 1 BCは0としてエンコードされる日曜日であり、月曜日は1などです。したがって、0 + y + y/4 - y/100 + y/400
this with y -= m < 3
は、今年の12月31日または前年(月に応じて)の曜日を計算します)。注:365 % 7 == 1
は、365*y
ではなくy
を記述した理由を説明しています。最後のコンポーネントd
は、前月の前日から曜日のカウントを開始するため明らかです。
説明する必要がある最後の部分は配列の値です。最初の2つの値は、昨年12月31日から月の開始までの日数% 7
です。残りの月については、7を法とする負の値前の月の終わりから現在の年の12月31日までの日数です。言い換えれば、7を法とする加算によって日数を引いています。 (a-b)%7 = (a+(7-b%7))%7
。
私のブログ投稿であなたが見つけるかもしれないより多くの説明。