陳凱 上海市位育中學
唐代孫誧寫過一篇名叫《一行算法》的文字,看名字它很像學術著作,其實是一首詩:
一行尋師觸處游,
到天臺后始應休。
因知算法通天地,
溪水尋常盡逆流。
詩末原跋講了一個有趣的故事:一行窮大衍算法,求訪師資不遠千里。嘗至天臺國清寺,見一院古松,門有流水。一行立于門屏,聞僧于庭前布算之聲,謂其徒曰:“今日當有弟子自遠來,求吾算法……門前水合卻西去,弟子當至。”一行聞其言而入,稽首請法,授其術,而門外舊東流水,忽改而西流矣。撇開故事中積極配合演出的具有超現實主義特征的溪流不談,今人考證認為,一行在天臺山學習的很有可能是某種與歷法相關的計算方法。同時,這個故事還印證了古人所說的算術和算法就是同一個意思。
吳文俊認為,中國古代數學是算法化的數學,而不是公理化的數學。今人讀古人算學方面的著作,能感受到其相當統一的特征:針對某一類型的問題給出一個普遍適用的計算過程。舉例說,南北朝時期,張丘建著有《張丘建算經》,其中創設了一個“女不善織,日減功遲”的情境,說其初日織五尺,末日織一尺,三十日織訖,問織幾何。由于每天減少的織布量都相等,給人一種并非“不善織”,倒更像是處心積慮地磨洋工的感覺。對于提出的“織幾何”之問,張丘建給出了明確的算法:并初末日織布數半之余以乘織訖日數。這其實就是等差數列求和的公式:首項加末項乘以項數除以二。到了宋代,人們對等差數列有了更深入的研究,沈括的《夢溪筆談》第十八卷中有如下記載:“隙積者,謂積之有隙者,如累棋、層壇及酒家積罌之類。雖似覆斗,四面皆殺,緣有刻缺及虛隙之處,用芻童法求之,常失于數少。余思而得之……古書所不到者,漫志于此。”書中詳細描述了求解高階等差數列的方法,作者還特別提出“古書所不到者,漫志于此”,其創新精神值得贊賞。到了元代,朱世杰進一步給出了任意高階等差數列求和的普適性的方法。
西方的算法一詞“algorithm”源于對波斯學者花拉子模(Khwarizmi)的音譯,而在中文語境中,“算法”一詞的含義自古至今是一貫的,且幾乎是不言自明的。說起信息技術或信息科技學科教師,相信他們都認為是能夠理解“算法”一詞的概念的,且認為算法部分的教學活動,是能夠甚至于說是最適合用來落實計算思維培養目標的。但結合具體的教學活動設計來思考計算思維培養的落實,仍會生出不少疑惑。例如,若直接套用數列求和公式,用語句s=(1+n)*n/2求出從1開始的等差數列和,在這個過程中,到底哪里體現出計算思維的培養?怎樣的算法設計過程能體現計算思維的運用?甚至還可以這樣問:一行、張丘建、沈括等人是否具有計算思維?
使用算法解決問題,一般可分為抽象與建模、設計算法、編寫程序、調試運行這樣幾步。其中,抽象與建模的過程與計算思維的運用相對來說有著更緊密的聯系,可以重點圍繞這一步來考察多種不同的用計算機進行等差數列求和的過程在思維方法上的區別。下頁圖1所示的是1、2、3直到10的數列求和的三種不同的算法。

圖1 三種1、2、3直到10的數列求和的算法
第一種方法只是簡單地將數列求和的需求用符號表達了出來,很難讓人感受到其中有抽象和建模的過程,若數列項很多,就完全無法利用自動化的優勢(無論是對計算機還是對人來說);第二種方法直接套用了等差數列求和公式,這個公式的獲得過程本身,的確是體現了抽象和建模的過程,這種抽象與建模更多和數學思維方法的運用(如數形結合)有關,但代碼的編寫者極有可能只是簡單地了解公式的作用并應用了這個數學思維的成果而已;對于方法三,直觀上感覺其中的確經歷了抽象和建模的過程,并且也能感知到這種抽象和建模的過程與方法二有所不同,但若進一步追問其中究竟抽象了什么,又建模了什么,與方法二區別在哪里,就很難回答了。若說方法三中的遞歸的運用就是一種抽象和建模,或者也可以引用他人的“遞歸是一種抽象的表達方法”的觀點,但這仍然未能點明所抽象的是什么的問題,也就是說,到底是從哪些事物中抽取出共同的、本質的特征的這樣一個問題,仍然沒有得到解答。
哲學家鮑德里亞提出過對不同“擬像”的分析。擬像的第一序列是符號對真實的表征,但很容易被發現符號與真實的區別;在擬像的第二序列中,符號表征逼近真實,因此符號表征和真實之間的界限是模糊的;在擬像的第三序列中,擬像的世界高于真實,擬像具有非指涉性,它不是對某物的再現而是其自身的展現,具有某種扭曲真實的能力。使用藝術的例子能更容易理解鮑德里亞的想法,阿爾塔米拉洞窟中的公牛繪畫就是第一序列擬像的例子,正如鮑德里亞所說的那樣,是“藝術是對現實拙劣的模仿”;超級現實主義的藝術品(請注意與超現實主義相區分)講究一種對真實的極致再現,可以看作是第二序列擬像的例子;而數字技術所創造出來的不具有現實對應物卻具有真實感的虛擬場景,則是第三序列擬像的例子,鮑德里亞稱其為仿真(Simulation)。
很有意思的是,仿真(Simulation)也是計算機科學中常用的概念,通常指一個程序模擬某一種事物的行為。Simulation和Emulation這兩個詞語都被翻譯成仿真或模擬,但兩者是有區別的:Simulation是行為上的仿真,它模仿的是一個對象外在的行為,而對象內部要實現這種模擬,可能會采取與事物本身并不一致的方法;而Emulation是一種過程上的仿真,它要求這種模擬能對應對象真實的內部運作的狀態,并且由內部的模擬過程來達成對象行為上的仿真。
本文要討論的,不是用算法去對某個事物實施仿真,而是考察算法自身是不是一種仿真。不妨試著將算法看成是人類創造的藝術品,而需要去模仿的則是人類實現計算的思維過程,那么就很容易借用鮑德里亞的理論對不同類型算法中思維運用的特征進行分別。在上一節的第一種方法中,“s=1+2+3+4+5+6+7+8+9+10”的語句并沒有完成對人類解決問題的思維過程的刻畫,換句話說,它相當于對某一計算裝置交待任務,要求其求出1、2到10的數列的和,至于計算裝置如何實現此功能,卻和此算法的設計者無關。因此可以說,這樣的算法沒有實現任何對人類思維過程的擬像。
但算法的確可以對思維過程進行一種“拙劣”的模仿,注意,這里的“拙劣”一詞并不自帶褒貶的意味。例如,讀者可以自行設想在頭腦中對數列進行累加的過程,比較多見的變化場景可能是這樣的:首先,頭腦中浮現出左面一個1和右面一個2這兩個數字的影像(或者還會有后續的3、4、5等數字,但可能會因為注意力的轉移而“失焦”),當1和2相加得到3的時候,右面原來的2也同時變化為3(在某些想象中,可能是某個新出現的3擠入了原來2的位置),然后進入到下一輪,實施3加3得6的計算,與此同時,右面原來的3變為4。可以將這個想象過程描繪成一個虛擬的運算機器,如圖2所示,細線箭頭表示的是運算動作的第一步,左側相加的動作可以和右側加1的動作同時進行,或不分先后地進行,粗箭頭表示的是運算動作的第二步,同樣,兩個動作可以同時進行,或不分先后地進行。這個算法從行為上看,是和一些人的思維過程一致的。
反復執行以上過程,并輔以監督,用來在恰當的時候停止運算,圖2中所寫的是“當到達10時則執行最后一步”,而不是“當到達11時停止”,意圖是盡量趨近人的思維習慣。這個算法很容易用程序代碼編寫出來,于是可以說,可以用符號作為思維過程的抽象。值得一提的是,可以參照如圖3所示的電路原理圖搭建出電路,其中采用了寄存器、加法器、比較器和緩沖器芯片,其運行契合符號表達的算法,也契合人的思維過程,于是,對現實中思維過程的抽象又反過來實體化為現實中的變化過程。

圖2 一種常見的可在頭腦中實施的求數列和的思維過程演示
可以用此算法比對教學中常見的用循環語句解決數列求和問題的算法,這里稱為方法四,如圖4所示,可發現此方法與圖3所示的更接近真實思維過程的方法存在部分偏離。例如,存儲空間初始值不是從1、2開始,加法計算也需要嚴格分步驟按順序進行,這種偏離往往會成為理解算法的思維路途中的堵塞點,而偏離的原因是,當今的算法大多是為通用且異步執行指令的計算機架構設計的。

圖3 使用多種芯片實現數列求和的原理圖

圖4 一種更契合常見的算法(但可能偏離人的慣常思維)的求數列和的思維過程演示
這里來對比上一節所提到的第二種方法,也就是直接套用數列求和公式的方法進行分析,就能發現,方法二中程序代碼中的求和實施過程,和人的思維中的求和實施過程,在行為上是一致的,換句話說,代碼的編寫者不可能在不知曉求和公式的用途的情況下,就采用這個公式進行計算。對于一個進行心算或筆算的人來說,數列求和公式具有某種自動化的效果,這種效果在數學公式被轉換為程序代碼后繼續存在,因此,計算機中的算法成了人的思維過程的一種擬像。但方法二的擬像只能屬于第一序列的擬像,這是因為當聚焦于細節時,計算機的運算過程就變得和人很不一致了。例如,人做6加4運算的具體過程必然和計算機是不同的。由于到目前為止,或者,在可想象的未來相當長的時間內,在物理程度上對人腦思維運作的還原是難以達成的,所以算法就難以達成逼近人類思維真實的擬真。鮑德里亞曾提及博爾赫斯的小說《關于科學的精確性》,小說中描述了一個關于地圖制作者將地圖繪制得如此精細以至于能精確地涵蓋帝國領土的每一處,致使地圖和現實之間無法區分的故事。對計算機算法來說,要實現如此程度的對思維過程的擬像,是既不可能也沒有必要的。
如果說方法二中所體現出來的是第一序列的擬像,那么方法四所體現出來的,是否與方法二類似,同樣是一種對人類思維的行為上的模仿呢?在細致觀察后可認為,在方法四中,除去對人的思維過程在行為上模仿這一事實,它不僅存在著一種有意為之的對人的思維過程的偏離,還存在著為了實現不可能達到第二序列擬像效果的一種在內在過程級別(Emulation)上的填補,在填補過程中需要引入某些不能對應現實已有事物的新的設定。
第三序列的擬像是一種當前沒有對應現實實體的創造物,是一種對真實的超越。仔細思考一下,若將算法視作一種藝術,那么當它在被某個人用作計算時,無論是心算、筆算或編寫成程序代碼使用,都可以看成是第一序列的擬像,這種符號化的算法最多只能在外在行為上對人類思維進行模擬,它不可能具有趨近人的思維底層完全還原出物理運作過程的能力。然而,當試圖將算法轉換成為一種自動化的裝置時,一種數字化創造的真實就取代了真正的現實。思考這樣一個例子,想象一個虛擬的機器人是如何根據用循環語句實現數列和累加的代碼執行運算過程的,如圖5所示。可以想象出,機器人會在圖示右側的指令和圖示左側的存儲空間之間來回穿梭,根據指令對存儲空間的數據進行改寫。

圖5 想象中一個機器人如何執行指令改寫數據
盡管容易設想一個機器人能夠逐個執行指令,但對于機器人如何執行#3指令,還是會讓人生出疑惑,因為#3其實是一個針對指令本身應當如何執行的指令。想象機器人內部有一系列的齒輪,在執行#1的時候,這些齒輪以某種虛構的方式轉動著,在完成#1指令后,機器人執行#2,此時這些齒輪又以某種虛構的方式轉動著,但在機器人面對#3指令中“重復做”的時候,人的頭腦的理性會說,這里齒輪的轉動,一定存在著某些和先前的轉動本質上不同的地方,但頭腦卻很難虛構出足以能說服自己的某種存在截然區別的轉動方式。雖然如此,當代人的頭腦又傾向于認為,#3指令應當是可以實現的(不妨想象一下古人會輕易認同嗎)。當教師講授循環語句結構的時候,似乎不會有學生來質疑循環結構本身的存在,但熟知CPU架構的教師自己內心知道,支撐循環結構的語句是由人創設出來的文本,它需要翻譯成一系列的對應電平信號變化的底層機器指令才能真正得到運作。所以說,對于當今的學生或大部分編寫計算機算法的人來說,算法儼然就是超越真實的擬像。
不妨想象一下,如何用繪制想象中的機器人的運行過程來描述使用遞歸實現數列求和,也就是前文提到的方法三的例子,其中遇到的最大的難點,是在機器人執行遞歸函數調用自身時,這種描繪是如何實現的。一種合理的想象是,機器人每次執行遞歸函數就會復制自身結構并幻化出一個新的機器人(筆者最早是在特級教師陳大波老師的課上看到這樣的描繪方法,并且,至今還未能設想出更好的描繪方法),對比物理現實,這種想象顯然頗有魔幻色彩,但在符號化的世界中卻能毫無障礙地演示出完整的遞歸過程。相較于方法四中循環的方法,方法三中的遞歸不僅從行為上模擬了運算過程,更是模擬了運算過程得以機械化實現的可能方式,因此,相對循環語句結構,用遞歸實現指令的重復執行,更具有內在過程模擬(Emulation)的特點。
鮑德里亞曾提出擬像先行的概念,這個概念描述了人們逐漸遠離對現實的直接經驗而進入到以符號為基礎的仿真環境中的過程。“先行”其實暗示了一種“后行”,第三序列的擬像有著拉扯現實的作用,也就是說,為了使得先行的概念真正在數字世界中以虛擬物的形式運行起來,就必須反過來對現實進行改造。歷史上,圖靈首先創設了純粹作為思維實驗的圖靈機,在多年后圖靈完備的計算機真正被制造出來,可看成是擬像先行的一個案例。筆者認為,計算思維應當和擬像的先行以及這種先行的擬像反向改造現實的過程有關。舉例說,某問題的解決雖然可以用枚舉算法得到解決,但若學生在思考問題解決的方法時,便已經被告知了枚舉的方法,那么枚舉就成了一種可被實際使用的超真實之物,計算思維因而隱遁,計算思維的培養目標就難以實現。反之,如果要求學生對虛擬計算裝置的運行原則先行加以設定,然后根據這些設定構造模型,這樣就可能會產生出對應枚舉、遞歸、并行處理等多種模型——雖然這些模型均已存在,但在教學過程中,需要假設它們尚未被創設出來,然后再逆向地在現實中尋找支撐實現這個模型的可用之物,這是一種與數學思維有很大區別的抽象與建模的方式。
本文試圖從擬像理論的角度,對先前提出的問題給出回答,僅供參考。
1.直接套用數列和公式的算法是否體現出計算思維的運用?該算法設計者至少知道,存在著一種可解決問題的數學模型,并且知道可以借助計算機代替人來實現計算。但若僅此而已,便停留在第一序列的擬像,無關計算思維的運用。
2.怎樣的算法設計過程能體現計算思維的運用?算法的設計者應當認知到,現有的計算模型是一種擬像的虛擬物,對這種虛擬物的使用本身不體現計算思維的運用,所以要么重構模型,要么利用已有模型創設出新的模型,這種創設新模型的目標將產生一種驅動力,使設計者要么利用和改造已有的現實中的裝置,要么利用和改造那些已有的基于現實裝置的虛擬模型,使這個作為新目標的模型運轉起來。
3.一行、張丘建、沈括等人是否具有計算思維?計算思維的運用需要計算機科學發展與數字化技術被廣泛應用的時代背景,一行、張丘建、沈括等應當沒有運用計算思維的機會。問一個有趣的問題,如果他們穿越到當代,是否能學會如前文方法三或方法四中運用循環語句實現數列求和的方法?筆者認為完全有可能,但就算是這樣,也難以斷定他們在求解問題的過程中,運用到了計算思維,除非他們產生出一種構建新的計算模型的目標并將其實現。