鄭興航 江蘇省錫山高級(jí)中學(xué)
我國(guó)大學(xué)計(jì)算機(jī)專業(yè)許多在起始階段都?xì)w在數(shù)學(xué)系,后來才逐漸分離獨(dú)立,這種現(xiàn)象說明計(jì)算機(jī)學(xué)科的誕生和數(shù)學(xué)學(xué)科有著千絲萬縷的聯(lián)系。計(jì)算思維概念脫胎于計(jì)算機(jī)專業(yè),而數(shù)學(xué)思維概念的提出則源于數(shù)學(xué)。筆者發(fā)現(xiàn),從對(duì)數(shù)學(xué)問題解決過程入手,師生比較容易辨清與把握計(jì)算思維實(shí)質(zhì)。
筆者所在學(xué)校信息技術(shù)課程“數(shù)據(jù)與計(jì)算”模塊主要采用項(xiàng)目方式組織學(xué)生進(jìn)行學(xué)習(xí)。第一階段以使用海倫公式求三角形面積作為樣例貫穿教學(xué)始終,隨著預(yù)設(shè)條件不斷增加,順序、分支、循環(huán)、面向過程與面向?qū)ο缶幊痰戎R(shí)應(yīng)用被漸進(jìn)嵌入到項(xiàng)目中。第二階段為基本算法進(jìn)階,力圖通過不同問題的解決,幫助學(xué)生了解窮舉、回溯和二分等算法的基本思想。
學(xué)生以Python語言為背景,首先學(xué)習(xí)賦值、輸出語句的書寫格式,了解語句含義。為幫助學(xué)生掌握順序結(jié)構(gòu)編程的方法,教師布置了一道思維上沒有難度的基礎(chǔ)訓(xùn)練題,要求學(xué)生在三條邊的長(zhǎng)度分別為5、6、7的條件下,用海倫公式編程求出三角形面積,并輸出結(jié)果,海倫公式由教師預(yù)先給出。為滲透模塊調(diào)用方法,本次編程需要在程序第一行,用import語句導(dǎo)入math模塊,以便在程序中順利使用sqrt函數(shù)。按照教師課前設(shè)想,學(xué)生編寫的代碼應(yīng)與圖1所示的程序類似。
圖1
剛剛學(xué)習(xí)編程,語句格式寫錯(cuò)是學(xué)生常犯的錯(cuò)誤。但在幫助學(xué)生調(diào)試程序的過程中,教師發(fā)現(xiàn),一個(gè)班級(jí)經(jīng)常有5到6位同學(xué)編寫的程序就像圖2所示的程序一樣,單條語句并沒有錯(cuò)誤,但語句放置的順序不對(duì),而且錯(cuò)誤雷同。課后與其他信息技術(shù)教師交流,他們反映其他班級(jí)也有類似現(xiàn)象。教師當(dāng)時(shí)只是將這種現(xiàn)象簡(jiǎn)單歸結(jié)為學(xué)生編程習(xí)慣還沒有養(yǎng)成。半年后在與數(shù)學(xué)老師的一次交流中,筆者突然認(rèn)識(shí)到這種現(xiàn)象的出現(xiàn)并不偶然,這不僅僅是學(xué)生對(duì)賦值語句沒有理解,而是與學(xué)生經(jīng)過多年的數(shù)學(xué)課程學(xué)習(xí),已經(jīng)養(yǎng)成的數(shù)學(xué)思維習(xí)慣有關(guān)。數(shù)學(xué)關(guān)注前后邏輯關(guān)系,強(qiáng)調(diào)由因到果,但在表達(dá)某個(gè)結(jié)論時(shí),其涉及的約束條件經(jīng)常是放在后面做補(bǔ)充說明,對(duì)順序并不像程序設(shè)計(jì)要求那么嚴(yán)苛。
圖2
通過上述發(fā)生的教學(xué)事件,筆者認(rèn)為可以通過列舉一些數(shù)學(xué)問題,讓學(xué)生體悟數(shù)學(xué)思維與計(jì)算思維在問題解決中發(fā)揮的不同作用來認(rèn)識(shí)它們之間的區(qū)別與聯(lián)系,從而加深學(xué)生對(duì)計(jì)算思維抽象與自動(dòng)化本質(zhì)的理解。
為幫助學(xué)生糾正前文提及的程序編寫錯(cuò)誤,在后來的教學(xué)中教師有意識(shí)地對(duì)原來的教學(xué)設(shè)計(jì)進(jìn)行了修改。增加教學(xué)環(huán)節(jié),安排學(xué)生先在紙張上寫出數(shù)學(xué)解題的一般步驟,然后再啟發(fā)學(xué)生思考,這些解題步驟要轉(zhuǎn)換成計(jì)算機(jī)可以接受的程序,需要對(duì)數(shù)學(xué)的解題步驟做哪些變通與調(diào)整,即引導(dǎo)學(xué)生將思維方式從數(shù)學(xué)推理模式對(duì)應(yīng)遷移到應(yīng)用計(jì)算模式,同時(shí)畫出流程圖。在比較中理解程序設(shè)計(jì)中的p=(a+b+c)/2語句的本質(zhì)是指揮計(jì)算機(jī)從內(nèi)存調(diào)用已經(jīng)準(zhǔn)備好的變量a、b、c的值,在運(yùn)算器中按照一定規(guī)則進(jìn)行計(jì)算,再把結(jié)果存儲(chǔ)到變量p所表示的內(nèi)存中,與數(shù)學(xué)中所指的p=(a+b+c)/2有本質(zhì)不同。為此,在執(zhí)行p=(a+b+c)/2語句之前,需要先在內(nèi)存中開辟三個(gè)空間,分別命名為a、b、c,并用a=5,b=6,c=7三條賦值語句在這三個(gè)空間中存入具體數(shù)值。a、b、c、p代表的四個(gè)物理空間有了具體數(shù)值之后,才能應(yīng)用海倫公式計(jì)算三角形面積s。
能夠運(yùn)用順序結(jié)構(gòu)描述問題解決的一般步驟,并且認(rèn)識(shí)到用計(jì)算機(jī)處理問題一般要經(jīng)歷數(shù)據(jù)準(zhǔn)備、數(shù)據(jù)計(jì)算、輸出結(jié)果三個(gè)階段,標(biāo)示計(jì)算思維初步形成。
組合數(shù)學(xué)是學(xué)生高中階段數(shù)學(xué)學(xué)科中需要學(xué)習(xí)的一個(gè)重要模塊。為得到組合數(shù)計(jì)算公式,數(shù)學(xué)教師授課一般會(huì)經(jīng)過下述步驟:
(1)引導(dǎo)學(xué)生通過若干案例分析,認(rèn)識(shí)加法與乘法原理;
(2)作為乘法原理的具體應(yīng)用,得到排列計(jì)算公式A(m,n)=m*(m-1)*......*(m-n+1);
(3)在排列中去除有序性,順理成章得到組合數(shù)計(jì)算公式C(m,n)=m*(m-1)*......*(m-n+1)/n!=m!/(n!*(m-n)!)(公式一);
(4)根據(jù)集合的一一對(duì)應(yīng)關(guān)系得到公式C(m,n)=C(m,m-n),再根據(jù)某一元素取與不取,根據(jù)元素分類原則,分類統(tǒng)計(jì)得到公式C(m,n)=C(m-1,n-1)+C(m-1,n)(公式二)。
教學(xué)過程中輔之若干具體應(yīng)用,數(shù)學(xué)學(xué)科學(xué)習(xí)主體任務(wù)即算完成。在整個(gè)學(xué)習(xí)過程中,學(xué)生分類思考、分步計(jì)算、對(duì)應(yīng)變換等數(shù)學(xué)思維得到了訓(xùn)練與培養(yǎng)。
相同問題遷移到信息技術(shù)課堂,還要求學(xué)生對(duì)具體數(shù)值求出具體結(jié)果。學(xué)生需要接著思考用什么算法、程序如何編寫,才能將組合數(shù)結(jié)果計(jì)算出來。不同于數(shù)學(xué)中的“數(shù)”,計(jì)算機(jī)程序涉及的“數(shù)”是有具體數(shù)據(jù)范圍的,數(shù)據(jù)規(guī)?;蛴?jì)算結(jié)果較大有可能造成數(shù)據(jù)溢出。公式一計(jì)算直接用Python實(shí)現(xiàn),整數(shù)較大時(shí)會(huì)自動(dòng)轉(zhuǎn)換為浮點(diǎn)數(shù),會(huì)影響精度,需設(shè)計(jì)算法避免這種情況發(fā)生,如用高精度。用計(jì)算機(jī)解決問題不僅要考慮結(jié)果的正確性,在現(xiàn)實(shí)環(huán)境下,某些場(chǎng)景對(duì)計(jì)算速度和所占的空間大小要求嚴(yán)苛,為計(jì)算組合數(shù),Python提供了多種計(jì)算方法,如遞歸、動(dòng)態(tài)規(guī)劃等,遞歸實(shí)現(xiàn)會(huì)出現(xiàn)重復(fù)計(jì)算,而動(dòng)規(guī)需要開設(shè)更多空間。兩種算法實(shí)現(xiàn)的具體程序如下頁圖3、圖4所示。
圖3
圖4
在組合數(shù)計(jì)算的這個(gè)例子中,數(shù)學(xué)思維體現(xiàn)在梳理問題內(nèi)在邏輯聯(lián)系、找出規(guī)律、列出公式。計(jì)算思維不僅關(guān)注數(shù)量關(guān)系,還關(guān)注初始數(shù)據(jù)的范圍、中間數(shù)據(jù)的存儲(chǔ),及思考由此帶來的不同空間與時(shí)間復(fù)雜度等,以及用不同算法把結(jié)果算出來的效率和效益。
信息學(xué)奧林匹克競(jìng)賽的許多試題創(chuàng)意都是來源于日常生活,但欲求出最終結(jié)果,無論是數(shù)學(xué)模型建立,還是在空間與時(shí)間受到限制的條件下編程實(shí)現(xiàn)都不是一件容易的事情,需要較強(qiáng)的抽象思維能力及其他高階思維深度參與。例如,受廣場(chǎng)舞和走步鍛煉身體刷微信步數(shù)啟發(fā),全國(guó)信息學(xué)奧林匹克聯(lián)賽就出過一道求“微信步數(shù)”試題,對(duì)原題改編,將多維降為二維,題目大意是:
地面上有一個(gè)n行、m列的田字格,喜歡走步刷微信的朋友小C準(zhǔn)備在這個(gè)田字格上按照一定規(guī)則走步鍛煉身體,具體規(guī)則由k個(gè)按順序排列的二維數(shù)組(c1,d1)、(c2,d2)、(c3,d3)、……(ck,dk)構(gòu)成,其中ci=x或y,x表示要求小C沿著橫向走,y表示沿著縱向走;di=1或者-1,表示向前或向后走一步。小C每天只選一個(gè)交叉點(diǎn)開始按規(guī)則走步,并不斷重復(fù)這個(gè)規(guī)則,直到他走出了場(chǎng)地范圍才結(jié)束一天的走步計(jì)劃(走完第k步后,若小C還在場(chǎng)地內(nèi),他將重復(fù)規(guī)則繼續(xù)走下去,當(dāng)然也有可能永遠(yuǎn)結(jié)束不了)。小C每天走步所選的交叉點(diǎn)互不相同,很顯然完成全部計(jì)劃小C需要n*m天。問完成全部走步任務(wù),小C總共走了多少步?如果完不成任務(wù)則輸出-1。
非常有意思,為鍛煉思維,從純數(shù)學(xué)角度看,這道試題可以成為小學(xué)生的分類思維題,將情境分成兩類:一類是可以結(jié)束的游戲,一類是無法結(jié)束的游戲。對(duì)于可以結(jié)束的類型,只要分點(diǎn)計(jì)算和統(tǒng)計(jì),一定會(huì)得到明確結(jié)果;對(duì)于無法結(jié)束的游戲,引導(dǎo)學(xué)生找出內(nèi)在約束條件,即k步走步規(guī)則,分縱橫向,前進(jìn)與后退的步數(shù)總和均為零,而且在田字格中至少存在一點(diǎn),從這一點(diǎn)出發(fā),一輪走步結(jié)束后,小C仍然回到了原點(diǎn)。問題還可以再進(jìn)一步延伸討論,一輪走步走不出邊界的本質(zhì),是從這一點(diǎn)出發(fā),左右、上下移動(dòng)產(chǎn)生的位移的最大值都超越不了邊界。用計(jì)算機(jī)實(shí)現(xiàn),即是對(duì)走步規(guī)則,先分橫向與縱向,再分左右與上下,順序統(tǒng)計(jì)求最大位移。
如果思考這道問題的對(duì)象是中學(xué)生,可引導(dǎo)學(xué)生換一個(gè)角度思考,在游戲結(jié)果不會(huì)出現(xiàn)-1的前提下,讓學(xué)生從單點(diǎn)求解、求和入手轉(zhuǎn)換為統(tǒng)一整體考慮,想象有n*m個(gè)人在田字格中按照規(guī)則同時(shí)走步,統(tǒng)計(jì)每一步走步人數(shù),很顯然第一步走步人數(shù)為n*m,隨著規(guī)則的繼續(xù),不斷有人走出邊界,人數(shù)持續(xù)減少。規(guī)則相同,用計(jì)算機(jī)實(shí)現(xiàn),就是循環(huán),直到所有人走出田字格,游戲結(jié)束。
思維品質(zhì)再一次提升到競(jìng)賽層次,尋找n*m個(gè)人走出田字格的內(nèi)在規(guī)律。
模擬第一輪走步,分縱橫向研究每一步產(chǎn)生的影響,發(fā)現(xiàn)縱橫向之間相互獨(dú)立。對(duì)橫向一行中的n個(gè)點(diǎn),按照規(guī)則走到第i步時(shí),向左側(cè)移動(dòng)積累的最大位移為li(負(fù)整數(shù),即到第i步,每行有|li|個(gè)人已從左側(cè)走出了田字格),向右側(cè)移動(dòng)積累的最大位移為ri(正整數(shù),即到第i步,每行有ri個(gè)人已從右側(cè)走出了田字格),一行剩下的n-ri+li個(gè)人下一步對(duì)走步貢獻(xiàn)就是n-ri+li;同理,對(duì)縱向一列的m個(gè)點(diǎn),設(shè)到i步時(shí),向下方移動(dòng)積累的最大位移為di(負(fù)整數(shù),即到第i步,每列有|di|個(gè)人已從下方走出了田字格),向上方移動(dòng)積累的最大位移為ui(正整數(shù),即到第i步,每列有ui個(gè)人已從上方走出了田字格),一列剩下的m-ui+di個(gè)人下一步對(duì)走步的貢獻(xiàn)就是m-ui+di。因此,走下一步時(shí),田字格中剩下的總?cè)藬?shù)為(n-ri+li)*(n-ui+di),也是下一步對(duì)走步結(jié)果的的貢獻(xiàn),i=0,1,2…k-1(i表示初始狀態(tài)或上一輪的集結(jié)狀態(tài))統(tǒng)計(jì)求和,即得到第一輪所走的總步數(shù)。
第一輪走完,橫向整體產(chǎn)生的移動(dòng)距離用a表示,剩余人數(shù)為x=n-rk+lk;縱向整體產(chǎn)生的移動(dòng)用b表示,剩余人數(shù)為y=muk+dk。進(jìn)一步研究發(fā)現(xiàn),從第二輪開始,下面每一輪橫向走出田字格的人數(shù)均為|a|,縱向走出田字格的人數(shù)均為|b|。從第二輪開始,前i步橫向走出田字格的總?cè)藬?shù)用xi表示,縱向用yi表示。容易得到循環(huán)輪數(shù)為T=min(int(x/|a|),int(y/|b|)),用數(shù)學(xué)公式表達(dá),第二輪開始所走的主要步數(shù)為:
x,a,y,b,xi(i=0,…,k-1),yi(i=0,…,k-1)的值,在編程計(jì)算時(shí)可先行預(yù)處理得到。歸納出一般的計(jì)算公式,數(shù)學(xué)思維的深度參與,使得這道題目的運(yùn)算規(guī)模從(n*m)2降到min(n,m)*k,從科學(xué)計(jì)算角度看,這是質(zhì)的躍升。
本題程序?qū)崿F(xiàn)所占篇幅較長(zhǎng),有興趣的讀者可以登錄網(wǎng)站(https://www.luogu.com.cn/)查看。
在數(shù)學(xué)領(lǐng)域,有很多問題到目前還沒有確定的研究結(jié)果,用不完全歸納法去驗(yàn)證是常用的探索研究方法,但當(dāng)數(shù)據(jù)規(guī)模較大時(shí),人工計(jì)算將是一件不可能完成的任務(wù),如哥德巴赫猜想、旅行商問題等。哥德巴赫猜想任一大于2的偶數(shù)都可寫成兩個(gè)質(zhì)數(shù)之和,從數(shù)學(xué)角度思考,不完全歸納驗(yàn)證很簡(jiǎn)單,將給定的偶數(shù)a分解為兩個(gè)質(zhì)數(shù)b,c之和,所有情況一一列舉出來,如果有一種分解得到的b,c均是質(zhì)數(shù),說明猜想對(duì)于具體的偶數(shù)是正確的。
隨著需驗(yàn)證數(shù)據(jù)規(guī)模的增大,用手工方法去計(jì)算,計(jì)算量越來越大,轉(zhuǎn)用計(jì)算機(jī)工具解決就變得相對(duì)簡(jiǎn)單。計(jì)算機(jī)運(yùn)算速度快,善于處理規(guī)律性問題,在計(jì)算機(jī)可以處理的數(shù)據(jù)范圍內(nèi),首先把所有質(zhì)數(shù)預(yù)處理出來,存儲(chǔ)在特定空間中,并用循環(huán)對(duì)每一偶數(shù)窮舉所有分解并驗(yàn)證,微秒時(shí)間內(nèi)可得到結(jié)果。不過用計(jì)算機(jī)解析出所有質(zhì)數(shù)有多種算法,如試除法、埃氏篩、線性篩等,選擇不同算法對(duì)存儲(chǔ)空間和運(yùn)算速度會(huì)有不同影響。同一問題用不同算法分析解決是培養(yǎng)學(xué)生計(jì)算思維的有效途徑(如圖5、圖6)。
圖5
圖6
通過對(duì)不同類型數(shù)學(xué)問題的討論,筆者發(fā)現(xiàn),數(shù)學(xué)思維與計(jì)算思維之間既相互區(qū)別又緊密聯(lián)系。數(shù)學(xué)思維重在從現(xiàn)象背后找出一般規(guī)律,并力爭(zhēng)將結(jié)論用公式形式化表達(dá)出來。計(jì)算思維強(qiáng)調(diào)前期數(shù)據(jù)準(zhǔn)備,中間數(shù)據(jù)計(jì)算與存儲(chǔ),后期數(shù)據(jù)輸出;針對(duì)具體數(shù)值,形式化表達(dá)的數(shù)學(xué)結(jié)論,在不同的計(jì)算思維方式指導(dǎo)下可以產(chǎn)生不同的計(jì)算實(shí)現(xiàn)方法。數(shù)學(xué)思維與計(jì)算思維在問題解決的不同階段可以各自發(fā)揮不同的作用;數(shù)學(xué)思維下思考難以完成的任務(wù)可以借助計(jì)算思維探索解決之道;數(shù)學(xué)思維品質(zhì)的提升,對(duì)問題內(nèi)在規(guī)律的發(fā)現(xiàn),可以同步提升計(jì)算思維品質(zhì)。