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