張化川 陳君 張悅 張力生
摘 要:表達式是程序設(shè)計語言的核心,涉及計算機中很多基本概念和方法。但在目前的教學(xué)中,這些內(nèi)容并沒有很好地被融入,導(dǎo)致大部分學(xué)生沒有從計算機層面理解表達式,最終影響學(xué)生對程序設(shè)計和編程的興趣。依據(jù)圖靈機、馮·諾依曼機、上下文無關(guān)文法等計算理論及逆波蘭式等編譯方法,融合程序設(shè)計和計算機運行實現(xiàn)中的內(nèi)容,文中設(shè)計了確定運算符求值順序的遞歸算法和表達式求值的循環(huán)算法,以CDIO中“做中學(xué)”教育理念為指導(dǎo),設(shè)計了對這兩個算法的紙上演算學(xué)習(xí)方法。依此方法,學(xué)生在演算的過程中不僅掌握表達式及相關(guān)程序設(shè)計的知識,還有效培養(yǎng)程序思維、遞歸思維,以及“0和1”思維等計算思維。
關(guān)鍵詞:計算思維;計算機表達式;CDIO
中圖分類號:TP311 文獻標(biāo)識碼:A
文章編號:2096-1472(2018)-07-56-04
1 引言(Introduction)
工程人才短缺和工程教育質(zhì)量問題是全世界面臨的共同課題[1]。計算機專業(yè)的教育是工程教育,計算機課程的教學(xué)質(zhì)量,特別是計算機基礎(chǔ)課程的教學(xué)質(zhì)量直接影響計算機工程人才培養(yǎng)質(zhì)量。在我國,高校計算機基礎(chǔ)課程普遍存在告訴學(xué)生“這是什么”,而不是“為什么是這樣”的現(xiàn)象[2]。計算機基礎(chǔ)教學(xué)面臨著新的改革,既要有相對穩(wěn)定的、體現(xiàn)計算機學(xué)科思想和方法的核心內(nèi)容,又要突出思維方法的訓(xùn)練[3]。在2010年九校聯(lián)盟(C9)計算機課程研討會上,與會專家就“如何在新形勢下提高計算機基礎(chǔ)教學(xué)的質(zhì)量、增強計算思維能力的培養(yǎng)”,明確提出將“計算思維”作為計算機基礎(chǔ)教學(xué)的核心任務(wù)[4]。
在計算機基礎(chǔ)教學(xué)中,計算機語言是其中的重要內(nèi)容,而要學(xué)好計算機語言,學(xué)好計算機表達式是基礎(chǔ)。因此,本文從計算機表達式的教學(xué)改革入手,探討計算機基礎(chǔ)教學(xué)中如何落實計算思維能力的培養(yǎng)。
2 計算機表達式(Computer expression)
計算機表達式是程序的重要組成部分,它來源于數(shù)學(xué)表達式,是數(shù)學(xué)表達式在計算機中的應(yīng)用;然而與數(shù)據(jù)表達式又不盡相同,它更側(cè)重的是數(shù)據(jù)在計算機中的表示和存貯方法、實現(xiàn)運算的方法、構(gòu)建和分解表達式的算法等應(yīng)用內(nèi)容,學(xué)習(xí)重點是實現(xiàn)方法及計算機基礎(chǔ)理論和知識。
2.1 數(shù)據(jù)的表示和存貯
根據(jù)馮·諾依曼機理論,計算機在處理數(shù)據(jù)時,先將數(shù)據(jù)存貯到內(nèi)存中,為了使用方便,從數(shù)學(xué)中引入了變量的概念,標(biāo)識數(shù)據(jù)對應(yīng)的二進制位串存放在內(nèi)存中的位置。從本質(zhì)上講,變量表示內(nèi)存中一組連續(xù)的存貯單元,用首地址和偏移表示其在內(nèi)存中的位置[5]。圖1描述了數(shù)據(jù)在計算機中的表示和存貯,為了便于初學(xué)者理解,用“長度”替換了“偏移”這個計算機術(shù)語。
2.2 運算
在數(shù)學(xué)中定義了數(shù)的集合,然后在數(shù)的集合上定義運算,并用一個符號表示這個運算,這個符號稱為運算符,運算涉及的數(shù)稱為操作數(shù)。
計算機運算符來源于數(shù)學(xué)運算符。為保證計算機能存貯和處理數(shù)據(jù),計算機對不同類型的數(shù)據(jù)使用不同的二進制表示方法,從而產(chǎn)生了數(shù)據(jù)和數(shù)據(jù)類型的概念。計算機對數(shù)據(jù)進行運算表示的是計算機處理數(shù)據(jù)的操作序列,即在馮·諾依曼機上處理數(shù)據(jù)的操作序列。
從本質(zhì)上講,運算是定義在數(shù)據(jù)類型上的,與數(shù)據(jù)類型緊密相關(guān),雖然有些運算可以處理不同數(shù)據(jù)類型的數(shù)據(jù),但具體實現(xiàn)的方法是不同的。若操作數(shù)的數(shù)據(jù)類型與運算規(guī)定的數(shù)據(jù)類型不同時,先要對操作數(shù)進行類型轉(zhuǎn)換[6]后再進行計算。因此,必須有數(shù)據(jù)類型的概念和意識才能夠理解計算機中的運算。初學(xué)者需要進行大量的訓(xùn)練,才可以建立這種概念和意識。
2.3 教學(xué)和學(xué)習(xí)重點
前文已經(jīng)明確從表達式和運算兩個層次學(xué)習(xí)計算機表達式。在表達式層次上,核心內(nèi)容是構(gòu)造一個需要的運算序列,學(xué)習(xí)重點定位于掌握確定表達式中運算的執(zhí)行順序的方法,著重培養(yǎng)計算思維[7]中的遞歸思維和程序思維。在運算層次上,核心內(nèi)容是構(gòu)造一個能在馮·諾依曼機上運行的操作序列,由于計算機中增加了很多計算機特有的運算,涉及到大量的計算機知識,以及計算理論中的原理和方法,初學(xué)者不可能一次性學(xué)習(xí)并掌握所有的運算,所以學(xué)習(xí)重點定位于掌握在馮·諾依曼機上執(zhí)行運算的方法,學(xué)習(xí)和掌握基本、常用的運算,提升學(xué)習(xí)能力,著重培養(yǎng)計算思維[7]中的“0和1”思維。
3 計算機處理表達式(Processing for expressions by computer)
培養(yǎng)和推進計算思維需要學(xué)生深入掌握計算機解決問題的思路[8]。如圖2所示,描述計算機中編譯表達式和計算表達式的過程,在此過程中體現(xiàn)了計算基本原理和方法。
3.1 編譯過程
對計算理論中的下推自動機、編譯原理中的逆波蘭式等基礎(chǔ)理論和技術(shù)進行分析,總結(jié)抽象出計算機編譯表達式的遞歸過程,并形成流程圖如圖2所示。
(1)若表達式中只有一個運算符,直接將序號記數(shù)器(序號計數(shù)器初始值為1)中的序號標(biāo)注給這個運算符,序號記數(shù)器加1。
(2)確定最后執(zhí)行的運算符。表達式中有多個運算符時,找到優(yōu)先級最低的運算符,若有多個優(yōu)先級最低的運算符,根據(jù)優(yōu)先級最低的運算符的結(jié)合性確定最后執(zhí)行的運算符。
(3)構(gòu)建子表達式隊列。如果在第(2)步確定的運算符是多目運算,則按照規(guī)定的操作數(shù)計算順序或編譯器規(guī)定的計算順序構(gòu)建子表達式列表;若是單目運算,則直接構(gòu)建子表達式隊列。
(4)從子表達式隊列中取出一個子表達式。采用遞歸方法依次確定各子表達式的運算符執(zhí)行順序。從隊列中取出一個子表達式,如果沒有子表達式,則計算機編譯完畢。如果取出的子表達式不包含運算符,繼續(xù)從隊列中取下一個子表達式;如果取出的子表達式包含運算符,則遞歸調(diào)用本算法,確定子表達式中運算符的順序。
3.2 計算過程
根據(jù)圖靈機及馮·諾依曼機等理論可知,CPU采用循環(huán)方式執(zhí)行程序的指令序列。為了便于理解,使用如圖3所示的循環(huán)算法,描述計算機計算表達式的過程。按照上節(jié)確定的運算符計算順序,從第1個運算符開始,依次執(zhí)行所有的運算符,直到結(jié)束。
(1)計算運算符。運算符的語義規(guī)定了在馮·諾依曼機上運行的操作數(shù)序列,無論運行在什么類型的計算上,CPU執(zhí)行的指令序列都是為了實現(xiàn)馮·諾依曼機的操作數(shù)序列。根據(jù)運算符的語義將操作數(shù)進行計算,得到計算結(jié)果。
(2)查找下一個需要計算的運算符。根據(jù)上級運算符的語義和前面的計算結(jié)果,依次判斷下一個運算符是否需要計算。
(3)判斷是否找到了需要計算的運算符。若找到,則返回第一步,計算運算符;若未找到,則遍歷了運算符序列。
計算表達式結(jié)束后,最后計算的結(jié)果即為表達式的計算結(jié)果。
4 表達式的教學(xué)實踐(Practice on expression teaching)
對初學(xué)者而言,可按照類似數(shù)學(xué)演算的方法,在紙上分編譯表達式和計算表達式兩步對表達式在計算機的處理過程進行演算,有效地將數(shù)學(xué)中的學(xué)習(xí)方法與能力平穩(wěn)遷移到程序設(shè)計的學(xué)習(xí)中,降低學(xué)習(xí)難度,提高學(xué)習(xí)效率。
4.1 運算表
目前大多數(shù)教材雖涉及了運算符的語法、語義、優(yōu)先級、結(jié)合律等運算相關(guān)的內(nèi)容,有些教材[6]也給出了計算機表達式中運算符的運算表,但大多數(shù)教材都沒有對運算符的語義進行準(zhǔn)確描述,對運算符的優(yōu)先級和結(jié)合性也只有簡單的描述,沒有深入講解,導(dǎo)致學(xué)生很容易對運算符理解錯誤。如有些教材中出現(xiàn)的“按運算符的優(yōu)先級別高低次序執(zhí)行”[9]的表述,導(dǎo)致學(xué)生誤解為計算機一定先執(zhí)行優(yōu)先級高的運算符,再執(zhí)行優(yōu)先級低的運算符。
目前大多數(shù)教材,無論是內(nèi)容的完備性還是組織形式,都不足以支持學(xué)生以計算機的方法計算表達式。針對這一現(xiàn)狀,對相關(guān)知識進行梳理,設(shè)計了包含運算符的運算名、結(jié)合性、語法和語義等的運算表,如表1所示。
在表1的運算表中只列舉了部分運算符的相關(guān)內(nèi)容,表中運算符按優(yōu)先級由高到低的順序依次列出,若優(yōu)先級是相同的,則用相同的底紋顯示。只有邏輯運算、條件運算符和逗點運算符等少數(shù)運算符規(guī)定了計算順序,其余運算符的計算順序由編譯器決定,或從左至右,或從右至左,但在同一個編譯器中,運算符的計算順序是唯一確定的。為了便于講解,在本文中,除了已經(jīng)規(guī)定了操作數(shù)計算順序的運算符,其余運算符統(tǒng)一為從左至右的計算順序。
學(xué)生在對一個實際的表達式進行分析時,首先確定運算符的計算順序,然后再根據(jù)確定的運算符計算順序?qū)Ρ磉_式進行求值,具體步驟如下。
4.2 確定運算符的計算順序方法
將表達式抄到一張紙上,表達式一定要寫在同一行,且下面需要有足夠的空行,然后按照如下步驟,確定表達式中運算符的計算順序。
(1)在表達式下面畫一條橫線,表示要計算這個表達式。如果表達式只有一個運算符,則直接在運算符上面標(biāo)注運算符的計算序號。
(2)如果表達式有多個運算符,根據(jù)優(yōu)先級和結(jié)合律找到最后計算的運算符。從橫線標(biāo)注的表達式中提取所有運算符,然后在運算表中逐個查找這些運算符的優(yōu)先級,找出最低優(yōu)先級的運算符,若只有一個,則此運算符就是最后計算的運算符;若有多個,則根據(jù)結(jié)合性找到最后計算的運算符。在最后計算的運算符下面畫一條豎線,并與橫線垂直相交,以表示該運算符,并將橫線標(biāo)注的表達式分解為多個子表達式。
(3)確定子表達式列表順序。在運算符表中查詢當(dāng)前運算符的形式化語法,確定形式化的“exp”代表的實際子表達式,按表中的操作數(shù)運算順序,確定子表達式的有序列表。
(4)采用遞歸方法依次確定各子表達式中運算符的計算順序。按照子表達式列表的順序依次取出子表達式,找到此子表達式中最后計算的運算符,在運算表中找到此運算符的形式化語法,確定形式化的“exp”代表的實際子表達式,按表中規(guī)定的操作數(shù)運算順序,形成另一個子表達式有序列表。若此子表達式除了最后計算的運算符再無其他運算符,則順序取出子表達式列表中的另一個子表達式,確定運算符的計算順序。
(5)直到表達式中所有的運算符標(biāo)上都執(zhí)行序號。
表達式x=c*f+(f/u-i%3)c、f、u、i分別為char、float、unsigned、int類型的變量,按照上面的方法最終確定的運算符計算順序如圖4所示。更詳細(xì)過程可參照文獻[10]。
4.3 表達式求值的演算方法
在上圖中,根據(jù)以下步驟直接演算表達式求值過程。
(1)根據(jù)畫出的運算符執(zhí)行順序圖,找到未執(zhí)行序號中,執(zhí)行序號最小的運算符。
(2)計算執(zhí)行序號最小的子表達式。根據(jù)運算符表中給出的運算符形式化語法,找到“exp”對應(yīng)的實際數(shù)據(jù),將實際數(shù)據(jù)代入到對應(yīng)的語義中替換“exp”,替換后根據(jù)語義進行計算,得到子表達式①的計算結(jié)果。若運算的操作數(shù)不滿足對數(shù)據(jù)類型的要求,還需要增加類型轉(zhuǎn)換操作,再進行計算,最后將計算的值和數(shù)據(jù)類型寫在執(zhí)行序號下面的橫線處。
(3)根據(jù)運算符的語義和前面的計算結(jié)果判斷是跳過下一個運算符繼續(xù)查找運算符,還是計算這一運算符。當(dāng)找到了需要計算的運算符,循環(huán)第(2)步。
(4)當(dāng)沒有了需要計算的運算符時,表達式計算完畢,最后一個被計算的運算符下的數(shù)據(jù)類型和值即為最后的計算結(jié)果。
表達式x=c*f+(f/u-i%3)按照上面的方法對表達式求值的順序如圖5所示。
需要注意,確定表達式的運算符計算順序并不是表達式求值的順序,在有些表達式中,會直接跳過一些運算符的執(zhí)行順序?qū)Ρ磉_式求值,如表達式c=c>='A'&&c;<='Z'?c+32:c。
5 結(jié)論(Conclusion)
本文基于CDIO工程教育思想,以培養(yǎng)計算思維為目標(biāo),對計算機表達式提出教學(xué)改革的方法。從圖靈機、馮·諾依曼機、上下文無關(guān)文法等計算理論,以及逆波蘭式等編譯方法中,總結(jié)、抽象出確定運算符執(zhí)行順序的遞歸算法和按順序計算運算符的循環(huán)算法,并根據(jù)教學(xué)的需要,設(shè)計出確定運算符的計算順序方法和表達式求值演算方法,設(shè)計出與演算方法配套的包含形式化語法和半形式化語義等內(nèi)容的運算符表。在計算機存貯數(shù)據(jù)的教學(xué)中培養(yǎng)了學(xué)生的“0和1”思維;由于在計算機處理表達式的教學(xué)中使用了遞歸思想進行分析,所以學(xué)生在紙上演算推理表達式的過程中培養(yǎng)了遞歸思維,達到了“做中學(xué)”的目標(biāo);同時,在學(xué)生分析計算機處理表達式中理解計算機執(zhí)行的過程,即培養(yǎng)學(xué)生的程序思維。
該教學(xué)改革方法于2010年應(yīng)用于我校軟件工程專業(yè),經(jīng)過8年多的教學(xué)實踐證明,學(xué)生自主學(xué)習(xí)程序設(shè)計的時間明顯增加,能讀懂?dāng)?shù)據(jù)結(jié)構(gòu)中算法的學(xué)生比例,以及具有較好編程能力的學(xué)生比例明顯提高,近五年麥可思中國大學(xué)就業(yè)報告顯示,我校軟件工程專業(yè)畢業(yè)學(xué)生的就業(yè)質(zhì)量處于重慶市前列。
參考文獻(References)
[1] 李竹林.基于CDIO教育理念的高校計算機專業(yè)課程教學(xué)改革探討[J].教育與職業(yè),2012(20):127-128.
[2] 周虹,富春巖,劉越.大學(xué)計算機基礎(chǔ)課程的創(chuàng)新與實踐[J].教育探索,2014(3):39-40.
[3] 馮博琴.對于計算思維能力培養(yǎng)“落地”問題的探討[J].中國大學(xué)教學(xué),2012(9):6-9.
[4] 佚名.九校聯(lián)盟(C9)計算機基礎(chǔ)教學(xué)發(fā)展戰(zhàn)略聯(lián)合聲明[J].中國大學(xué)教學(xué),2010(9):4-9.
[5] Bjarne,Stroustrup.王剛,譯.C++程序設(shè)計原理與實踐[M].北京:機械工業(yè)出版社,2010.
[6] 錢能.C++程序設(shè)計教程(第二版)[M].北京:清華大學(xué)出版社,2005.
[7] 陳國良,董榮勝.計算思維的表述體系[J].中國大學(xué)教學(xué),2013(12):22-36.
[8] 譚浩強.研究計算思維,堅持面向應(yīng)用[J].計算機教育,2012(21):45-49.
[9] 譚浩強.C++程序設(shè)計[M].北京:清華大學(xué)出版社,2004.
[10] 張化川,楊林,黎在萬.基于計算思維的計算機表達式教學(xué)方法實踐[J].現(xiàn)代計算機,2017(05):7-10.
作者簡介:
張化川(1979-),男,碩士,實驗師.研究領(lǐng)域:計算機基礎(chǔ)教學(xué),軟件建模及測試方法.
陳 君(1981-),女,碩士,講師.研究領(lǐng)域:軟件工程,數(shù)據(jù)挖掘.
張 悅(1993-),女,碩士生.研究領(lǐng)域:軟件工程.
張力生(1965-),男,碩士,教授.研究領(lǐng)域:計算機基礎(chǔ)教學(xué),數(shù)據(jù)挖掘與大數(shù)據(jù)分析.