陳凱 上海市位育中學
考慮這樣一個簡單的任務:有某個列表,規(guī)定其中所存儲的數(shù)據(jù)處于非1即0的兩種狀態(tài)之一,要求學生按枚舉的方式編寫算法,將列表中存儲狀態(tài)取反,也即將所有的1變?yōu)?,將所有的0變?yōu)?。請問,學生在任務實施過程中,有沒有運用到計算思維?又憑什么理由說有或者沒有運用到計算思維呢?后一個問題顯然更難以回答。因為教師可能有這樣的感覺:在此任務的實施過程中無論如何都可能涉及一些計算思維的運用,但若想進一步解釋哪里涉及了計算思維的運用,卻又難以言說了。那么,不妨換個角度加以詢問:學生在何種情況下實施這個任務以及怎樣實施任務,能更好地體現(xiàn)出計算思維的運用?舉例說,有以下幾種情況。情況A:學生已經學習過在列表中查詢所有的奇數(shù)并打印的算法和程序代碼,要求學生將已學習過的算法和程序代碼稍加改造,用于新布置的狀態(tài)取反任務;情況B:學生已經學習過在列表中查詢所有的奇數(shù)并打印的算法和程序代碼,要求學生利用陌生的積木式圖形編程環(huán)境編寫算法來實現(xiàn)狀態(tài)取反任務;情況C:學生已經學習過在列表中查詢所有的奇數(shù)并打印的算法和程序代碼,此時被要求在了解了一定的圖靈機的規(guī)則后,按圖靈機的運行方式編寫算法來實現(xiàn)狀態(tài)取反任務。對于以上三種情況,教師們可能有一種朦朧的感覺,似乎情況B和情況C的任務實施過程,對計算思維的要求更高。在這里,筆者試著借用“濃度”一詞,來描述任務中對計算思維方面能力的要求的程度。當然,對于具體任務的差異與計算思維濃度的關系,是否能在一定程度上取得共識,尚需要在較大規(guī)模的調查后方能得到結論。本文聚焦的是另一個問題,即教師直觀上會對任務實施產生出計算思維濃度差異的感覺,其根本原因是什么?圍繞這個問題,本文給出若干假設,可作為深入調查研究的線索,值得在實際的教學工作中加以驗證。提出這些假設的目的是解答這樣的疑惑:在某特定任務的實施中,模式識別、解構和抽象等思維的運用,是如何上升為具有計算機科學特征的計算思維的?
設想一下,幾乎每個人在用數(shù)字計數(shù)的時候,其行為都是自然而然的,在計數(shù)過程中,頭腦不會明顯意識到逢十進位的規(guī)則。而一些對二進制已經非常熟悉的人,他們在計數(shù)時,也同樣會感覺到二進制數(shù)碼的變化過程是自然而然的,也許只有當被問及是如何知道每次增加1之后數(shù)碼的變化,大概才會隱約感覺到計數(shù)過程中各個數(shù)碼所發(fā)生的類似于套娃一般的變化規(guī)律。人的頭腦在把握二進制計數(shù)過程中對數(shù)碼變化的感覺,與在古老的九連環(huán)拆裝過程中所體驗到的有相當程度的類似。而初學二進制的人則更有可能根據(jù)逢二進一的規(guī)則,用邏輯來推導出數(shù)碼的變化。對于已經相當熟悉十進制或二進制計數(shù)的人來說,若要制作出一個能夠計數(shù)的裝置,那么更重要的,恐怕不只是識別出某種模式,而是要挖掘出某種模式,前者是人的頭腦自然而然的行為,后者是人用某種機械化的方式對原本自然而然的行為進行模擬。以二進制計數(shù)為例,可能被挖掘出來的模式是多樣的。例如,可以由每個數(shù)碼相互影響的連鎖反應來挖掘出某種規(guī)律:經觀察可知,每一次加1,最后一個數(shù)碼的狀態(tài)總是取反,而只有當數(shù)碼的狀態(tài)由1轉而為0時,它左側也就是高位的數(shù)碼狀態(tài)才取反,這個連鎖反應可以一直向更高位傳遞下去;或者,也可以從加1的頻率和數(shù)碼的狀態(tài)之間挖掘出規(guī)律(數(shù)碼之間的相互影響反而是可以忽略的),可以注意到,每次加1,最后一個數(shù)碼狀態(tài)總是取反,而每次加2,高位的數(shù)碼狀態(tài)總是取反,每次加4,更高位的數(shù)碼狀態(tài)總是取反,以此類推。當然,存在更多可能被挖掘出的變化模式,如采用特定的遞歸或迭代的算法都可以實現(xiàn)二進制計數(shù)的數(shù)碼變化,而這些規(guī)律對于數(shù)碼變化過程實施的效果,都與二進制計數(shù)逢二進一的數(shù)學規(guī)則實施的效果是一致的。變化模式的多樣性,為計算的機械化實現(xiàn)提供了多種多樣的可能。
這里給出另一個例子,假設有一串數(shù)字為1、121、12321、1234321,如問下一個數(shù)字會是多少,顯然應該是123454321,為后續(xù)行文方便,不妨稱其為金字塔計數(shù)。每個人都不妨回想一下,自己是如何在頭腦中按當前模式變換出下一個數(shù)字的。以下是某一種常見的思維模式的示例,當在頭腦中念出121的時候,“2”這個數(shù)字在心中留下了特別深刻的印象,從而為下一輪的變化做好了鋪墊,相對地,從1到2的變化,以及從2到1的變化,反而是自然而然進行的。于是,在下一輪念數(shù)的一開始,頭腦就先將2轉變?yōu)?,然后自然而然地從1計數(shù)到3,并同時對“3”這個數(shù)字進行了特別加深的記憶,以便為下一輪變化做好鋪墊……這可能是人的頭腦在金字塔計數(shù)中實現(xiàn)模式識別的最好方法了。若是編寫某個算法,主要以模擬人的思維過程的方式來實現(xiàn)金字塔計數(shù)當然是可以的,不過顯然,存在更多種實現(xiàn)此類變換的方式。下面給出兩種不同的方法:比如,對列表[0,0,0,0,1,0,0,0,0]中的數(shù)據(jù)進行迭代,將所有存在著的非0的數(shù)字,以及雖然是0但旁邊是1的數(shù)據(jù)加1,顯然,借助簡單的枚舉算法就可以將列表變換為[0,0,0,1,2,1,0,0,0],若再進行一次替換列表就變成[0,0,1,2,3,2,1,0,0],以此類推?;蛘咭部梢钥紤]采用分形的方式來實現(xiàn)變換,假設用“*”符號的數(shù)量來表示某個數(shù)字,那么,如允許在變換過程中引入某些臨時的符號,就可以設計一套特定的規(guī)則進行符號的替代變換并實現(xiàn)金字塔計數(shù)。一種可行的方案是這樣的,初始符號串為“<*.>”,其中“.”為數(shù)字之間的分割,“<”和“>”代表數(shù)字的邊界,接下來只要反復實施將“*.”變?yōu)椤?*.”、將“<”變?yōu)椤?*.”、將“>”變?yōu)椤?.>”的替換,就能實現(xiàn)本節(jié)金字塔計數(shù)任務了。由這些例子可以看出,計算思維中的模式識別,更多具有挖掘隱含規(guī)律的意味。
無論是機械化的二進制計數(shù),還是分形式的金字塔計數(shù),可以看出,它們在實現(xiàn)過程中的變化模式與人日常思維的模式都有很大的差別,所以,當任務的目標確定為實現(xiàn)某個自動計算的裝置或算法時,可以借由觀察這種思維方式上的差異,來估計計算思維的濃度。
假設學生將要實施的任務是:判斷某個數(shù)字的奇偶性,如果是奇數(shù),則對該數(shù)乘以3再加1,如果是偶數(shù),則對該數(shù)除以2。很容易用流程圖描述算法,在流程圖中可以看到有判斷數(shù)字奇偶性的判斷框,有數(shù)字乘以3加1的處理框,有數(shù)字除以2的處理框等。假設將這個流程圖的各個部分拆成零件,然后將這些零件交給另一個人,并向其告知整個任務的目的,那么此人應當較為容易推測出,由流程圖拆為零件的各個部分在功能上的意圖。
不過,在某些時候,局部的構件的行為,只有放在整體的視野下才具有意義。例如,利用計數(shù)頻率和二進制數(shù)碼的狀態(tài)的關系設計如下計數(shù)方法。步驟1:寫八個0和八個1放置在一行;步驟2:再寫兩遍四個0和四個1放置在下一行;步驟3:再寫四遍兩個0和兩個1放置在下一行;步驟4:再寫八遍一個0和一個1放置在下一行。其過程如下頁圖1所示。被拆解出來的前三個步驟似乎與二進制計數(shù)的功能是無關的,只有在實施最后一步時,才能領會到,所有的步驟與二進制計數(shù)有著整體上的聯(lián)系,從而產生出從縱向上看數(shù)字的變化正對應著二進制計數(shù)的效果。
圖1 注:只有在步驟4實施過程中,才能實現(xiàn)計數(shù),并顯現(xiàn)出前面步驟的意義
這里再舉一個例子??紤]這樣的情況,某個二進制運算裝置并不以“0”作為“0”,以“1”作為“1”,而是以信號出現(xiàn)位置作為判別數(shù)值的依據(jù)。例如,下頁表中的數(shù)據(jù)表示的是二進制數(shù)“0111”。看上去就好像有個撥碼開關,往上撥為“1”,往下?lián)転椤?”。這里姑且稱之為撥碼二進制。
用信號的位置表示二進制數(shù)值
怎樣用這樣的裝置來進行計數(shù)呢?一種可行的程序代碼和運行效果如圖2所示。和上面的例子類似的是,從代碼中也很難直接看出逢二進一的數(shù)學規(guī)則。
圖2 一種二進制計數(shù)的方法
從上述例子可以看出,一個自動化過程或裝置的解構和構造,常常具有復雜系統(tǒng)中層級模擬和功能涌現(xiàn)的特點,這個特點有時會因為高度的模塊化封裝而被遮蔽起來。例如,用Python語句來實現(xiàn)兩個數(shù)字相加的運算,簡單的一句print(a+b)就能實現(xiàn),但何以能實現(xiàn)這個功能?即便深入到兩個數(shù)字的相加是如何用底層機器指令描述的,人們還是無法知曉機器到底是怎樣實現(xiàn)加法操作的,只有將指令和硬件電路當作一個整體來了解時,才能領悟到運算器、控制器、存儲器三者在實現(xiàn)任務時錯綜復雜的關系和此計算何以可行在整體上的原因,這種領悟無疑需要更多更強的計算思維能力。筆者并不是想說,教師們一定要在教學中解釋計算機底層工作的原理,而是想說,僅僅用超級簡略的五大邏輯部件的計算機架構圖紙或者十來行實現(xiàn)某簡單任務的程序代碼來當作教學內容,并宣稱能實現(xiàn)計算思維的培養(yǎng),這是相當可疑的。
計算思維中的抽象與數(shù)學上的抽象有怎樣的區(qū)別?數(shù)學上的抽象保留了量的關系和空間形式,而舍棄了非數(shù)學的一切特征,往往有著抽象概念逐級提高的特點。而一個計算裝置為了真正制造上的可能性,有對抽象之物實體化的特點,并且,計算裝置中的實體化,既有為了實現(xiàn)更廣泛的他物的需求而升級的趨勢,也有為了實現(xiàn)自身而尋求基礎元件的降級的趨勢。下面用一個用數(shù)字邏輯實現(xiàn)的二進制加法的裝置來具體說明,圖3所示是一個二進制加法模塊處理兩個輸入數(shù)據(jù),并得到兩個輸出數(shù)據(jù)的演示。
圖3 二進制加法輸入和輸出的三種情況
圖4 實現(xiàn)兩個二進制數(shù)字加法的半加器
將加法器模塊分解成兩個邏輯門后,可發(fā)現(xiàn)這兩個邏輯門本身仍然是抽象的概念,還可以繼續(xù)向更底層尋得使其能具有邏輯運算能力的更基礎的元件,那就是三極管。三極管仍然是抽象的概念,直到尋得物理上的實體的晶體管或電子管。
圖5 實現(xiàn)三個二進制數(shù)字加法的裝置
如果使用前面所說的撥碼二進制的形式組裝一個二進制加法器,結構就完全不同了。圖6所示是一個可對兩個二進制撥碼進行加法運算的裝置。
圖6 一種撥碼二進制加法裝置
以上所舉的數(shù)字電路的例子主要是用來說明,每一種抽象的功能元件,用以實現(xiàn)其功能的基礎實體是多樣的;而每一個作為基礎的實體元件,用于構建整體功能的方式也是多樣的。一個樸素的假設是,計算思維能力較強者,能更靈活地依賴抽象元件的實體化的多樣性來解決問題。
本文從模式識別、解構、抽象三個角度給出了關于計算思維濃度的假設,認為某個任務若對計算思維能力有較高的要求,需要實施者對模式的挖掘、局部構件對整體行為的模擬、可實體化的抽象這三點有所作為。
考慮這樣一個任務,即編寫算法計算第n項斐波那契數(shù)列項的值。比較容易想到的方法是,設立某列表,列表的第一項和第二項都存入數(shù)字1,借助循環(huán)語句使列表之后每一項都是前兩項之和。如果試著將算法的行為實體化,就可以想象出這樣的畫面:某個機器跨騎在列表第一項和第二項的位置上,它通過兩個信號讀取傳感器讀入列表兩個項的值,機器將兩個值相加,然后向右移動列表一項的位置,當機器跨騎在第二項和第三項的位置時,將先前加法運算的結果寫在列表第三項的位置上,接下來,就是讀入第二項和第三項的值,以此類推……這種實體化的想象是多樣性的,也可以想象同時有許多機器都跨騎著三個列表項,每個機器都可以將左面兩個列表項的值相加存入最右面的列表項,這其實就用到多引擎計算的思路了,其實施步驟與前者有相當大的區(qū)別。在放開束縛進行實體化的想象時,須知這里所說的實體不一定是真正物理意義上的實體,如在用遞歸的方法計算斐波那契數(shù)列項的相關想象中,機器本身具有瞬間自我復制的能力。從培養(yǎng)計算思維角度看,在設計特定算法計算斐波那契數(shù)列項的時候,希望學生領悟到自己其實是在用一個現(xiàn)實世界中可能不存在的物件來實施某個計算任務,當然,這種可能不存在的物件在抽象的概念上是成立的,它自身是由更基礎的現(xiàn)實中可能存在的物件、或仍然可能不存在的物件模擬出來的。
除了無束縛地對抽象物件進行實體化可能性的想象,有時也可以經由特定的實體化的限制來啟發(fā)思維。假設這樣一個任務:只用一個存儲空間來存儲斐波那契數(shù)列項的數(shù)據(jù),并計算第n項的斐波那契數(shù)列項的值。一種可能的方法是,將變量值設為形如“101”的樣子,其中“0”之前“1”的數(shù)量代表第一項的值,“0”之后“1”的數(shù)量代表第二項的值。于是,任務就轉換成了如何將“101”變換成“1011”,繼而變換成“110111”。顯然,為了實現(xiàn)這種變換,就需要進一步挖掘出符號串變換的模式,然后用特定的算法來實施整個演化過程,從而模擬出斐波那契數(shù)列項的計算過程。
本文給出了一系列與模式識別、解構與抽象有關但又與日常思維中的模式識別、解構與抽象有一定區(qū)別的任務,并相信此類任務的實施需要較高的計算思維的濃度,但對于這個假設的科學論證,無疑還需要投入更多的時間、精力和資源。