1. 程式人生 > >用程式語言實現演算法

用程式語言實現演算法

課程導言

【用流程圖描述演算法,可以與使用者更好地交流。如果需要演算法在計算上執行,就需要把演算法用程式語言編寫為程式。在程式與演算法課程中,給出了計算長方形面積演算法的虛擬碼,虛擬碼比較直觀地描述了演算法的執行過程,但它不能在計算機上直接執行,需要把虛擬碼用一種程式語言轉換為程式。本篇和同學們探討如何用程式語言來實現演算法以及程式語言的發展過程。通過本篇的學習,你將瞭解到程式語言是如何由二進位制語言逐步發展為高階語言的,以及用Java語言如何實現計算長方形面積的演算法。】

語言是人類交流的工具,是人們溝通的主要表達方式。不同的民族有不同的語言,每種語言有自己的語法規則和詞彙,只有在規定的語法規則和詞彙範圍內,人們才可以相互理解之間的對話和語句文字要表達的內容。超出這個範圍,就會出現語言理解困難現象,例如:不同語言之間的人對話就會發生理解問題,就需要翻譯人員的協助才能完成正常交流。

程式語言是人類與計算機的交流工具,為了讓計算機能夠準確無誤地完成任務,人們需要使用計算機能夠讀懂的語言與之交流,編制任務指令交給計算機,計算機才能夠按部就班地執行指令,完成人們交給的任務,編寫計算機指令的語言就是程式語言。

程式語言和人類語言一樣,不是先天就有的,是隨著科技和計算機技術的發展,人們為了更好地控制計算機,幫助人們完成更多工,提高程式設計和工作效率而不斷對語言進行創新、完善和改進而來的。最初的程式語言是機器語言,也是計算機唯一能直接讀懂的語言。計算機只能識別二進位制程式碼,所以機器指令也是由二進位制程式碼組成的,所謂的機器語言,就是直接用二進位制程式碼編寫計算機的指令序列(程式)。

假設編寫一個計算直線方程的程式,給出方程的斜率、變數係數和變數X的值,求Y值,將計算結果儲存到以Y為地址的儲存單元中。

直線方程為 Y = AX + B,其中A、X、B已經分別儲存到A、X、B儲存單元,機器指令可以直接定址到該儲存單元。A單元的儲存地址為26H,X的儲存地址為34H,B的儲存地址為36H,Y的儲存地址為56H,其中26H、34H、36H、56H均為16進位制,該演算法流程圖見下圖。 

0099.png

圖1 計算直線方程流程圖

根據流程圖編寫的機器指令序列(參考了IBM-PC指令集,可能有出入,主要是為了說明程式語言的演變過程):

1

2

3

4

5

6

7

8

9

10

11

11011  AX  26H     

存取指令,讀取指定地址26H的儲存內容到AX暫存器;

21001  34H

乘法指令,將34H儲存地址的內容與AX暫存器內容相乘;

31011  26H  AX

存取指令,將AX暫存器內容儲存到26H地址的儲存單元;

41011  AX  36H

存取指令,讀取指定地址36H的儲存內容到AX暫存器;

50011  AX  26H

加法指令,將AX暫存器內容和26H地址儲存內容相加;

61011  56H  AX

存取指令,將AX暫存器內容儲存到56H地址的儲存單元。

上面就是用機器語言編寫的計算直線方程的計算機指令序列,是不是特別難記、難懂,完全是看天書的感覺。為了提高程式設計的工作效率,在1949年,人們將助記符和機器程式碼關聯起來,並編寫了轉換程式,轉換程式可以把助記符轉換為機器程式碼,這就是組合語言。

根據流程圖編寫的彙編程式指令序列(參考了IBM-PC指令集,可能有出入,主要是為了說明程式語言的演變過程):

1

2

3

4

5

6

7

8

9

10

11

(1)    MOV  AX  A

存取指令,讀取A地址的儲存內容到AX暫存器;

(2)    IMUL  X

乘法指令,將X儲存地址的內容與AX暫存器內容相乘;

(3)    MOV  A   AX

存取指令,將AX暫存器內容儲存到A地址的儲存單元;

(4)    MOV  AX  B

存取指令,將B地址的儲存內容讀取到AX暫存器;

(5)    ADD  AX  A

加法指令,將AX暫存器內容和A地址儲存內容相加;

(6)    MOV   Y  AX

加法指令,將AX暫存器內容儲存到Y地址的儲存單元;

用助記符代替了機器碼,程式設計是不是相對簡單了一些,轉換程式可以幫助程式設計人員從繁重的機器碼編寫勞動中解脫出來,轉換程式也稱之為彙編編譯程式,其工作原理如下圖所示: 

 blob.png

圖2 彙編編譯程式原理圖

彙編程式碼完成後,需要執行編譯程式,將彙編程式碼轉換為機器程式碼。由於不同CPU架構的計算機,其提供的指令集不同,支援執行的機器程式碼也不同,因此,要執行在不同CPU架構的計算機上,就需要執行支援該CPU架構的彙編編譯程式。例如IBM-PC機採用了Intel  X86系列處理器,微控制器一般採用ARM架構的系列處理器,如果要讓編寫的彙編程式執行在IBM-PC機上,就需要呼叫支援IBM-PC指令集的彙編編譯程式,如果要讓編寫的彙編程式執行在ARM架構的計算機上,就需要呼叫支援ARM指令集的彙編編譯程式。

組合語言相對機器語言來說,程式設計效率和可讀性都有了較大提高。但編寫程式還是過於繁瑣,並且組合語言對應一條條指令集,當指令集改變時,就得修改相應組合語言,導致其可移植性和維護性很差,不能跨平臺使用。為了解決這個問題,計算機工程師們繼續創新和改進程式語言,隨著計算機技術和科技的發展,計算機對語言的處理能力進一步提高,計算機工程師試圖用人們能夠容易識別和易懂的語言去編寫程式,在20世紀50年代,出現了第一批高階語言,包括FORTRAN 、LISP、COBOL等語言,隨後相繼出現了C語言、C#、Java、PHP、Perl等高階語言。

高階語言的優點是其語法和結構更類似漢字或者普通英文,並且由於遠離對硬體的直接操作,使得一般人經過學習之後都可以掌握程式設計技術。

●  根據計算直線方程流程圖編寫的C語言程式:

1

2

3

4

5

void  line(double a,double,x,double y)

{

a = ax;

y = a + b;

}

●  根據計算直線方程流程圖編寫的Java程式:

1

2

3

4

5

6

7

8

public  class  LineQuation 

{

void  line(double a,double,x,double y)

{

a = ax;

y = a + b;

}

}

Java語言和C語言都屬於高階語言,其語法和規則有相同之處,但也有很大的不同,Java是面向物件的語言,C語言是函式式語言,Java是編譯兼解釋性語言,C語言是編譯性語言,關於語言的特性後面會有陸續介紹。

我們寫程式用的是高階語言,要讓我們寫好的程式能夠在計算機上執行,就必須要把高階語言轉換成計算機能夠理解的機器語言,該轉換程式稱為該語言的編譯程式,例如C語言的轉換程式可以稱之為C語言編譯程式,C語言編寫的程式編譯為Windows程式的工作過如下圖所示:

blob.png

 圖3 編譯性語言編譯過程

編寫完成的C語言原始碼,首先經過編譯前處理器規範程式碼和預編譯,然後通過編譯器轉換為彙編程式碼,再由彙編器轉換為機器程式碼,最後由連結器將有關的機器程式碼檔案進行相互連結,構建Windows程式。

Java語言編寫的程式編譯為Windows程式的工作過如圖3-11所示,Java程式碼是文字檔案,可以用記事本等文字編輯器直接編輯Java檔案。程式碼編寫完成後執行Java編譯器,將Java原始碼檔案編譯為class檔案(位元組碼檔案),JVM(Java虛擬機器)的類裝載器載入class檔案,由直譯器解釋執行。

blob.png

圖4 Java語言編譯過程

程式與演算法課程中,給出了計算長方形面積演算法的虛擬碼,下面給出用Java程式語言實現演算法的程式碼,演算法的流程圖參見用流程圖描述演算法一課。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import java.util.Scanner;

public class RectangularArea {

public static void main(String[] args) {

// TODO Auto-generated method stub

//宣告num1、num2變數

int num1,num2;

//宣告Scanner變數,並用new運算子例項化Scanner

Scanner sc = new Scanner(System.in);

//提示使用者輸入長方形長度

System.out.println("請輸入長方形的長度");   

//呼叫Scanner方法nextInt()獲取使用者輸入

num1 = sc.nextInt();

//提示使用者輸入長方形寬度

System.out.println("請輸入長方形的寬度");   

//呼叫Scanner方法nextInt()獲取使用者輸入

num2 = sc.nextInt();

//判斷num1和num2是否小於0,如果小於零提示使用者並退出程式

if( num1 <=0 || num2 <=0 )

{

System.out.println("輸入的長度和寬度不能小於0");

//退出程式

System.exit(0);

}

//計算num1和num2的乘積

int result = num1 * num2;

//輸出長方形的面積

System.out.printf("長方形的面積為:%d",result);

}

}

程式語言是人們與計算機的交流工具,各種程式語言語法規則雖有不同,但其核心思想都是人們通過程式語言來控制計算機,讓計算機幫助人們解決各類問題。學習程式語言的目的是掌握利用計算機解決問題的能力,包括分析問題、演算法設計、資料架構等能力,有了這些能力,只要學會一種程式語言,其它語言都可以無師自通。

課程小結

1、明確瞭解決問題的演算法,也用流程圖繪製了演算法的詳細步驟,下一步就要用程式語言將演算法編寫為程式。最早的程式語言是二進位制語言,也是計算機唯一能識別的語言,就是用0和1兩個數字寫出的程式碼,計算機能夠識別二進位制語言,是因為計算機的指令就是用二進位制來描述的,關於二進位制的概念後面的課程會有講述。

2、二進位制語言都是0和1,程式碼晦澀難懂。假設現在讓程式設計人員用二進位制語言編寫程式,估計都要瘋掉。好在現在有Java、C#、python等高階語言了,寫的程式碼類似英語,簡單易懂。從二進位制語言到高階語言也是逐步發展的過程,為了擺脫繁重的二進位制程式設計勞動,提高程式設計效率,程式語言專家在二進位制語言的基礎上發明了組合語言,組合語言用助記符表示計算機指令,例如,用add表示兩數相加指令。用的加法指令時,就可以直接使用add,而不必寫一長串0和1的數字了。後來,人們又在組合語言的基礎上發明了高階語言,高階語言已經接近於人們可以直接理解的語言了。

思考與練習

1、請簡要敘述高階語言、組合語言、機器語言的區別。

2、相對二進位制語言來說,組合語言的助記符為什麼能提高程式設計效率?

3、Java編譯器的作用什麼?