之前和朋友聊天,大家聊到一個(gè)話題_什么叫智商高。這個(gè)當(dāng)然有很多答案,例如,我們聽(tīng)過(guò)的關(guān)于牛頓、愛(ài)因斯坦、費(fèi)曼、馮諾依曼的故事。有人說(shuō)非常快的心算是智商高的表現(xiàn),比方說(shuō)隨口說(shuō)一個(gè)歷史上的日期,讓你計(jì)算那是星期幾。
Dustin Hoffman 和阿湯哥Tom Cruise的電影《雨人rainman》的原型人物Kim Peek是一個(gè)自閉癥患者,他有超常的記憶和計(jì)算能力,在接受觀眾提問(wèn)的視頻中,他能在幾秒甚至更短的時(shí)間內(nèi)說(shuō)出日期對(duì)應(yīng)的星期幾。
電影《雨人》劇照
會(huì)做這種計(jì)算的人也叫Calendar Savant,常常被人神化。僅看日期計(jì)算這一點(diǎn),其實(shí)非常簡(jiǎn)單,有很多方法都可以做到這一點(diǎn)。
01
方法1_brute force
如果不想記任何東西,就可以在腦子里迅速計(jì)算年之間的差別,之后計(jì)算月的差別,再計(jì)算天數(shù)之差,要考慮閏年閏月,通過(guò)天數(shù)除以7的余數(shù)算星期幾。
如果記住365的倍數(shù)就可以加快很多。這個(gè)方法的缺點(diǎn)是計(jì)算量有點(diǎn)大。電腦的一個(gè)基本原理就是在內(nèi)存和運(yùn)算速度之間做權(quán)衡(time-memory tradeoff)。
下面要介紹兩個(gè)方法,只需5~6步也能學(xué)會(huì)快速計(jì)算日期對(duì)應(yīng)的星期數(shù),不過(guò)稍微要記一些規(guī)則。
02
方法2_YMD方法
以1989年1月13日為例,計(jì)算這一天是星期幾。
我太了解我的讀者了,一定會(huì)有人問(wèn)為什么選這天呢?沒(méi)有什么原因,如果一定要說(shuō)原因,那就是從那天開(kāi)始到今年某個(gè)時(shí)候,一共經(jīng)歷了10億秒。
步驟1_計(jì)算年份,用字母Y表示
取要計(jì)算的年份的后兩位數(shù)除以4,去掉余數(shù)。可以得到89/4_22,把得到的結(jié)果與年份的后兩位相加,22+89_111. 然后將所得的結(jié)果與之對(duì)應(yīng)年代的數(shù)字相加。
因此,對(duì)于1989年,得到關(guān)于年份的代碼Y_111+0_111.
步驟2_記住月份代碼,用M表示
計(jì)算的第二步需要在下面的列表中查找(所以要背下來(lái))對(duì)應(yīng)的代碼。
對(duì)于1989年1月,得到月份代碼M_0。
步驟3_找到日期代碼,用字母D表示
這一步是直接找日期本身的數(shù)字,對(duì)于1989年1月13日,D_13。
步驟4_計(jì)算Y+M+D的數(shù)字之和
第4步是將前面得到的三個(gè)數(shù)字Y,M,D相加,于是我們得到111+0+13_124。
步驟5_計(jì)算星期數(shù)
計(jì)算的最后一步是取余運(yùn)算,用步驟4得到的結(jié)果除以7取余數(shù),于是得到124除以7的余數(shù)為5,那天就是星期五。
看著步驟多,其實(shí)很簡(jiǎn)單,歸納起來(lái)如下圖所示_
接下來(lái),我們?cè)偎阋幌聬?ài)因斯坦的生日_1879年3月14日。按照上述步驟,得出_(79/4+79+2+3+14) _ 7 _ 5。
可得結(jié)果,愛(ài)因斯坦的生日是星期五。
03
方法3_末日算法
這個(gè)算法叫做“末日算法”。
假設(shè)每一年2月的最后一天(平年是28號(hào),閏年是29號(hào))是末日,因此每一年的4月4日,5月9日,6月6日,7月11日,8月8日,9月5日,10月10日,11月7日,12月12日的星期必然和末日的星期相同,因?yàn)?strong class="highlight-text">這些日期和末日相差的天數(shù)正好是7的倍數(shù)。
除此之外,因?yàn)槠侥暧?65天,閏年有366天,所以每過(guò)一個(gè)平年,末日的星期數(shù)加1,每過(guò)一個(gè)閏年,末日的星期數(shù)加2(365 _ 7 _ 1, 366 _ 7 _ 2)。
這樣一來(lái),只要我們知道某一年的末日是星期幾,就可以按照末日算法的思路快速地計(jì)算出目標(biāo)日期是星期幾。
接下來(lái),我們要介紹的計(jì)算方法需要分別記住兩組數(shù),其中一組是末日日,如下表所示_
另一組是年代對(duì)應(yīng)的錨點(diǎn)星期數(shù)_
同樣以1989年1月13日為例,計(jì)算過(guò)程如下_
① 用1989年的最后兩位數(shù)除以12,89除以12,商a_7,余數(shù)b_5;
② 用第1步得到的余數(shù)除以4取余數(shù),5除以4,余數(shù)c_1;
③ a,b,c相加,d_a+b+c_7 + 5 + 1_ 13;
④ 用d除以7,取余數(shù),13除以7,余數(shù)e_6;
⑤ 用余數(shù)e加上本年代的錨點(diǎn)星期數(shù),求出本年的末日,表格里可以查到1989年的錨點(diǎn)星期數(shù)是星期三,星期三+6_星期二;
⑥ 用當(dāng)月的末日日來(lái)計(jì)算要求的星期數(shù),第一個(gè)表格可以查到_1989年是平年,1月的末日是1月3日,為星期二,所以1989年1月13日是星期五。
04
總結(jié)
Brute force、YMD和末日算法這三種計(jì)算方法,都能算出愛(ài)因斯坦的生日(1879年3月14日)是星期五。
后兩種方法是高智商的人較為常用的計(jì)算方法,但需要記住代碼和錨點(diǎn),有一定的難度。雖然掌握了高智商的計(jì)算方法,但我們也需要勤加練習(xí),接下來(lái)講究的便是計(jì)算速度。