問(wèn)題:設(shè) 當(dāng)日 T 的日期是 公元 y 年 m 月 d 日,求 T 是 星期幾? 為了方便,我們用 0 到 6 的整數(shù)表示星期,0 表示星期日,1 到 6 分別表示 星期一 到 星期六。 (注:以下解答只適用于格里高利歷。) 設(shè) T 是 星期 w,公元1年1月1日 的前一天是 Z?,Z? 是 星期 w?,T 距離 Z? 過(guò)了 S 天,于是有: w = (w? + S) mod 7 ① 其中,mod 為 (w? + S) 除以 7 的 余數(shù)。 而 S = D' + D 其中, D' 為 y 年 1 月 1 日 的前一天 Z 距離 Z? 的累積天數(shù),D 為 T 在 y 年內(nèi)的 累積天數(shù)。 顯然,Z 距離 Z? 剛好是 過(guò)了 y - 1 年??紤] 一個(gè)平年有 365 天,再考慮閏年規(guī)定:
則 D’ = 365(y-1) + [(y-1)/4] - [(y-1)/100] + [(y-1)/400], 其中 [x] 表示 取 x 的整數(shù)部分。 注:[x + 1/2] 就是對(duì) x 四舍五入。 當(dāng) T 為 公元2019年1月1日 時(shí),D = 1,D‘ = 737059,查日歷知道 公元2019年1月1日 是星期二,即,w = 2 帶入 ① 有: 2 = (w? + 737059 + 1) mod 7 = (w? + 737058 + 1 + 1) mod 7 = (w? + 105294 ×7 + 2) mod 7 = (w? + 2) mod 7 求得: w? = 0 而: (365(y-1)) mod 7 = (364(y-1) + (y-1)) mod 7 = (52×7(y-1) + (y-1)) mod 7 = (y-1) mod 7 所有最終 ① 簡(jiǎn)化為: w = ((y-1) + [(y-1)/4] - [(y-1)/100] + [(y-1)/400] + D) mod 7 ② 接下來(lái),需要計(jì)算 年內(nèi) 累積天數(shù) D。考慮平年的情況,有: 設(shè), m 月 1日前 累積超出天數(shù) 為 P(m) 則: D = P(m) + 28 × (m - 1) + d ④ 接下來(lái),需要求 P(m)。考慮 2 月的特殊性,將 1 月 和 2 月 挪到 12 后面 變成 13 和 14 月,于是得到: 令, 對(duì)這些點(diǎn),進(jìn)行線性擬合: P(x) = ax + b 使用,最小二乘法, 有: 解方程的得到: 線性擬合圖形如下: 由于 2.6 = 13/5,而 P(x) 需要是整數(shù),于是令: P(x) = [13x/5 + b'] 嘗試 b' = 0.4 ,將 x = 0 到 11 帶入得到序列: 0, 3, 5, 8, 10, 13, 16, 18, 21, 23, 26, 29 這和 (5) 完全一致,于是 b' = 0.4 有效,進(jìn)而有: P(x) = [13 x / 5 + 0.4] = [13 (x + 4) / 5 - 13 × 4 / 5 + 0.4] = [13 (x + 4) / 5 - 10.4 + 0.4] = [13 (x + 4) / 5 - 10] 即, P(x) = [13 (x + 4) / 5] - 10 ⑥ 令, k = [(14 - m) / 12] 即,當(dāng) m 為 1, 2 月 時(shí),k = 1,m 為其它月份時(shí),k = 0; 又令, M = m + 12k; 即,當(dāng) m 為 1, 2 月時(shí),M 為 13,14 月,m 為其它月份時(shí),M = m; 于是,有: x + 4 = M + 1 于是 ⑥ 改寫為: P(M) = [13 (M + 1) / 5] - 10 但這是 沒(méi)有考慮 3月前累計(jì)天數(shù)的情況,根據(jù) (3) 需要加上 3月前累計(jì)天數(shù) 3 ,于是: P(M) = [13 (M + 1) / 5] - 10 + 3 = [13 (M + 1) / 5] - 7 帶入 ④ 得到: D = [13 (M + 1) / 5] - 7 + 28 × (m - 1) + d ④' 再 考慮 ② 式: w = ((y-1) + [(y-1)/4] - [(y-1)/100] + [(y-1)/400] + D) mod 7 由于 1, 2 月份 被計(jì)算為 13, 14 月,等于多算了一年,因此 需要再減去 1 年,于是,令: Y = y - k 將 ② 改寫為: w = ((Y-1) + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D) mod 7 ②' 分析對(duì)閏年的修正:
最終,將 ④' 帶入 ②'’ 有: w = ((Y-1) + [Y/4] - [Y/100] + [Y/400] + [13 (M + 1) / 5] - 7 + 28 × (m - 1) + d) mod 7 最終得到,答案1: w = (Y + [Y/4] - [Y/100] + [Y/400] + [13 (M + 1) / 5] + d - 1) mod 7 ⑦ 上面在進(jìn)行線性擬合時(shí),也可以選取 (5) 的部分點(diǎn)進(jìn)行擬合,例如,選取 y 值間距大于等于3 的點(diǎn): 同樣是最小二乘法,計(jì)算結(jié)果為: 考慮 a ≈ p / q, p = [q × 2.59 + 0.5],篩選 p 較小,|q × 2.59 - p| 也較小 (小于 0.1)的情況,寫成JavaScript代碼如下: 運(yùn)行上面的 JavaScript 得到: ['13/5', '31/12', '44/17', '57/22', '70/27'] 第一種情況 13/5 上面已經(jīng)分析過(guò)了,現(xiàn)在考慮 第二種情況 31/12: 令: P(x) = [31x/12 + b'] 嘗試讓 b' = 1/2,將 x = 0 到 11 帶入得到序列: 0, 3, 5, 8, 10, 13, 16, 18, 21, 23, 26, 28 這和 (5) 相比 最后一項(xiàng) 28 偏小,于是嘗試讓 b'=2/3,將 x = 0 到 11 帶入得到序列: 0, 3, 5, 8, 11, 13, 16, 18, 21, 23, 26, 29 第 4 項(xiàng) 11 又偏大,于是令 b' = (1/2 + 2/3) / 2 = 7/12,將 x = 0 到 11 帶入得到序列: 0, 3, 5, 8, 10, 13, 16, 18, 21, 23, 26, 29 終于和 (5) 完全吻合,于是 b' = 7/12 有效,進(jìn)而: P(x) = [31x / 12 + 7/12] = [31x / 12 + (7 + 2×12) / 12 - 2] = [31x / 12 + 31 / 12 - 2] = [31(x + 1) / 12] - 2 令 M' = m + 12k - 2,則 x + 1 = M',再考慮 3月前的累積天數(shù) 3,則有: P(M') = [31M'/12] - 2 + 3 = [31M'/12] + 1 于是: D = [31M'/12] + 1 + 28 × (m - 1) + d 帶入 ②'’ 有: w = ((Y-1) + [Y/4] - [Y/100] + [Y/400] + [31M'/12] + 1 + 28 × (m - 1) + d) mod 7 最終得到,答案2: w = (Y + [Y/4] - [Y/100] + [Y/400] + [31M'/12] + d) mod 7 ⑦' 考慮 ⑦ 式: w = (Y + [Y/4] - [Y/100] + [Y/400] + [13 (M + 1) / 5] + d - 1) mod 7 設(shè) Y 的世紀(jì) 為 c,Y 后兩位為 Y' = Y mod 100; 在一個(gè)世紀(jì)的 100 年里,星期偏移為: (100 + [99 / 4]) mod 7 = 5 如果 世紀(jì)最后一年 是 閏年,則 星期偏移 還要 加 1,即: 6 根據(jù)上面的計(jì)算結(jié)果,由于 公元1年1月1日 的前一天是 星期 日,故 公元1年1月1日 是星期 1,進(jìn)而 公元1年3月1日 是星期 4。 從 公元1年3月1日 開(kāi)始 每個(gè) 世紀(jì)元年的 3月1日 星期為: 觀察發(fā)現(xiàn) 世紀(jì)元年的 3月1日 星期序列為 每 4 年循環(huán)一次: 4, 2, 0, 5 又,因?yàn)?5 mod 7 = 5 mod 7 - 7 mod 7 = (5 - 7) mod 7 = - 2 mod 7, 循環(huán)序列可改寫為: 4, 2, 0, - 2 它是一個(gè)等差數(shù)列,令 C = c - 1,則有: D' = 4 - 2(C mod 4) 但是這是 每個(gè)世紀(jì)元年的 3月1日 的 星期偏差,我們要的是 每個(gè)世紀(jì)元年的 1月1日 前一天 的 星期偏差,于是 需要減去 3(1月1日 到 3月1日 的星期偏差) + 1(1月1日前一天到1月1日的星期偏差) = 4,即, D' = 4 - 2(C mod 4) - 4 = - 2(C mod 4) 又 C mod 4 = C - 4[C/4],故: D' = - 2(C - 4[C/4]) = 8[C/4] - 2C 由于我們從 3月1日 返回 1月1日 時(shí) 移入的 星期偏差 是平年的情況,因此 D'' 作為 每個(gè)世紀(jì)元年的 1月1日 前一天 的 星期偏差 已經(jīng)計(jì)算了 世紀(jì)閏年的情況,于是: Y + [Y/4] - [Y/100] + [Y/400] = D'' + Y' + [Y'/4] = 8[C/4] - 2C + Y' + [Y'/4] 進(jìn)而有: w = (8[C/4] - 2C + Y' + [Y'/4] + [13 (M + 1) / 5] + d - 1) mod 7 = (7[C/4] + [C/4] - 2C + Y' + [Y'/4] + [13 (M + 1) / 5] + d - 1) mod 7 即, w = ([C/4] - 2C + Y' + [Y'/4] + [13 (M + 1) / 5] + d - 1) mod 7 ⑧ 為了方便計(jì)算,改寫為: w = ([C/4] - 2C + Y' + [Y'/4] + [26 (M + 1) / 10] + d - 1) mod 7 這就是 蔡勒(Zeller)公式。 答案3:設(shè) 當(dāng)日 T 的日期是 公元 y 年 m 月 d 日,則 T 的 星期數(shù)為: w = ([C/4] - 2C + Y' + [Y'/4] + [26 (M + 1) / 10] + d - 1) mod 7 其中,[] 為求整數(shù)運(yùn)算,mod 為取余數(shù)運(yùn)算,C 為 Y 世紀(jì) - 1,Y' 為Y最后兩位數(shù);當(dāng) m = 1, 2 月份時(shí),Y = y - 1, M = m + 12,當(dāng) m 為其它月份時(shí),Y = y, M = m。 |
|