提到方程,用計(jì)算機(jī)解方程這個(gè)話題是一定會(huì)涉及的。我們在前面曾提到過計(jì)算機(jī)可以用來下棋,當(dāng)然它還有別的“本事”,比如把一種語言翻譯成另外一種,或者演奏樂器,等等。
我們在這里并不打算對下棋或者進(jìn)行語言翻譯等過于復(fù)雜的計(jì)算機(jī)程序進(jìn)行研究,我們想要分析的只不過是兩個(gè)極簡單的程序,但在這之前,還是要先來簡單地談?wù)動(dòng)?jì)算機(jī)的構(gòu)造。
我們在第一章曾提到過的,能用一秒鐘的時(shí)間進(jìn)行成千上萬次運(yùn)算的裝置,是計(jì)算機(jī)中負(fù)責(zé)進(jìn)行計(jì)算的部分,它叫作“運(yùn)算器”。事實(shí)上計(jì)算機(jī)中還包括控制器和存儲(chǔ)器(記憶裝置),控制器負(fù)責(zé)整體調(diào)控計(jì)算機(jī)的工作,存儲(chǔ)器的作用是存放數(shù)據(jù)和預(yù)定信號(hào)。除此而外,計(jì)算機(jī)中還有專門用于輸入新數(shù)據(jù)和輸出計(jì)算結(jié)果的裝置,打印機(jī)會(huì)幫助計(jì)算機(jī)將這些計(jì)算結(jié)果以十進(jìn)制的形式打印在專門的卡片上。
就像你所知道的那樣,我們可以用唱片或錄音帶錄下人的聲音,然后用機(jī)器反復(fù)播放。但這兩種錄音方式也有不同,用唱片錄音是一次性的,一張唱片只能錄一次,而用錄音帶就不一樣了。錄音機(jī)在錄制聲音時(shí),是借助一種特殊膠帶的磁性作用來進(jìn)行的,錄在錄音帶上的聲音,不僅可以反復(fù)播放,還可以把錄過的內(nèi)容“抹掉”再錄新的。每條磁帶都能反復(fù)使用,想要“抹掉”舊內(nèi)容,只要直接錄上新內(nèi)容就可以了。
計(jì)算機(jī)的記憶裝置與上述原理相同。計(jì)算機(jī)借助電信號(hào)、磁信號(hào)或機(jī)械信號(hào),將數(shù)和預(yù)定的信號(hào)錄到專門的磁鼓、磁帶或其他裝置上,這些數(shù)與信號(hào)可以隨時(shí)“讀取”,或隨時(shí)“抹掉”后重新錄入。在記憶或讀取這些數(shù)與信號(hào)時(shí),計(jì)算機(jī)所用的時(shí)間只不過是百萬分之幾秒而已。
存儲(chǔ)器內(nèi)包含著幾千個(gè)單元,其中的每個(gè)單元內(nèi)又有磁性元件等幾十個(gè)存貯原件。我們假定二進(jìn)制的存貯方式為:用數(shù)字1表示1個(gè)被磁化了的原件,用數(shù)字0表示沒有被磁化的元件。例如存儲(chǔ)器內(nèi)的每個(gè)單元里含有的元件數(shù)是25個(gè)(即有25個(gè)二進(jìn)制位數(shù)),其中第1個(gè)元件用來表示數(shù)的符號(hào)(+或-),第2~15個(gè)用來存貯數(shù)的整數(shù)部分,其余的10個(gè)記錄小數(shù)部分。圖11中顯示的是存儲(chǔ)器中的兩個(gè)單元,每個(gè)單元里都有25個(gè)數(shù)位,“+”號(hào)表示被磁化的元件,“-”號(hào)表示沒有被磁化的元件。我們首先來觀察第1個(gè)單元(虛線的作用是將表示符號(hào)的數(shù)位與其他數(shù)位區(qū)分開,逗號(hào)的作用是將整數(shù)與小數(shù)部分區(qū)分開),這個(gè)單元計(jì)入的數(shù)是二進(jìn)制的“+1011.01”,也就是十進(jìn)制的“11.25”。
圖11 存儲(chǔ)器中的單元
存儲(chǔ)器不僅可以用來存貯數(shù),它也可以用來存貯指令,我們所說的“程序”就由指令組成。現(xiàn)在我為你介紹所謂的三地址的計(jì)算機(jī)指令:為了記入指令,要將存儲(chǔ)器的單元分成4段,圖11中的第二個(gè)單元就被虛線分成了4段,第幾段就表示第幾道程序,每道程序都以數(shù)(編碼)的形式被記入存貯單元里。比如:
加——操作Ⅰ
減——操作Ⅱ
乘——操作Ⅲ
……
指令是如何被完成的呢?存貯單元的第1段是操作碼;第2、第3段是存貯單元的編號(hào)(地址碼),為了完成這一程序,應(yīng)從這兩段中抽取數(shù)字,第4段是用來存放所得結(jié)果的貯存單元的編號(hào)(地址碼)。比如,圖11中第2個(gè)單元所計(jì)入的數(shù)是二進(jìn)制的“11、11、111、1011”,也就是十進(jìn)制的“3、3、7、11”,它們代表的指令是:使用第3和第7存貯單元的數(shù)字完成第Ⅲ道程序(即乘法程序),將結(jié)果存入第11存貯單元。
接下來我們不需要像圖11中所顯示的那樣,將預(yù)先設(shè)定好的符號(hào)記錄下來,而是要直接用十進(jìn)制的形式把數(shù)和命令記錄下來。比如圖11中的第2單元,我們只需記錄:乘3711。
現(xiàn)在我們可以對兩個(gè)最簡單的程序進(jìn)行分析了。首先是第一個(gè):
這個(gè)程序的5個(gè)存貯單元記錄下了計(jì)算機(jī)上述指令進(jìn)行工作的過程。
首先指令1:要求計(jì)算機(jī)把第4單元和第5單元的數(shù)相加,將結(jié)果存入第4單元(取代第4單元的原存貯數(shù)據(jù))。計(jì)算機(jī)在第4單元記入的數(shù)是0+1=1,完成這條指令后,第4、第5單元所存貯的數(shù)應(yīng)該是:
(4)1
(5)1
再來看指令2:要求計(jì)算機(jī)把第4單元的數(shù)與它自身相乘(即算出它的平方),將結(jié)果12記到卡片上,箭頭的意思是將結(jié)果輸出。
接下來是指令3:要求計(jì)算機(jī)將操作轉(zhuǎn)移到第1單元。也就是說,要從指令1開始依次重復(fù)執(zhí)行各條指令。于是計(jì)算機(jī)開始重復(fù)執(zhí)行指令1。
指令1:把第4單元和第5單元的數(shù)相加,將結(jié)果存入第4單元,現(xiàn)在第4單元里的數(shù)據(jù)就變成了1+1=2:
(4)2
(5)1
指令2:把第4單元的數(shù)與它自身相乘,將結(jié)果22寫到卡片上。
指令3:將操作轉(zhuǎn)移到第1單元,也就是再次從指令1開始重復(fù)。
指令1:將2+1=3存入第4單元:
(4)3
(5)1
指令2:將3的平方32寫到卡片上。
指令3:將操作轉(zhuǎn)移到第1存貯單元。
……
現(xiàn)在我們已經(jīng)弄清楚了計(jì)算機(jī)的工作程序:按順序計(jì)算整數(shù)的平方,并將結(jié)果寫到卡片上。在這個(gè)過程中,不需要你親自去用手敲出每個(gè)數(shù),計(jì)算機(jī)會(huì)自己按順序把整數(shù)選出來并且逐一計(jì)算出它們的平方。只用幾秒鐘的時(shí)間,甚至是在不到1秒鐘的時(shí)間內(nèi),計(jì)算機(jī)就可以算出從1到10000的所有整數(shù)的平方。
不過,在實(shí)際的操作中,讓計(jì)算機(jī)計(jì)算整數(shù)平方的程序比我們所寫的這個(gè)程序可要復(fù)雜多了,而這個(gè)“復(fù)雜”的部分首先就出現(xiàn)在指令2。要知道,將結(jié)果寫在卡片上所用的時(shí)間要比完成一道程序多好多倍,所以計(jì)算結(jié)果出現(xiàn)以后并不能及時(shí)地被記入卡片,而是要先被“寄存”在存儲(chǔ)器中的“空”單元里,然后再被“慢條斯理”地寫在卡片上。具體的方法是這樣的:第一個(gè)結(jié)果寄存進(jìn)第一個(gè)空單元,第二個(gè)結(jié)果寄存進(jìn)第二個(gè)空單元,第三個(gè)結(jié)果寄存進(jìn)第三個(gè)空單元……而我們所舉的例子里所寫的程序就沒有詳細(xì)到這個(gè)地步,關(guān)于這個(gè)內(nèi)容提也沒提。
除此而外,我們還有一個(gè)內(nèi)容沒有提到,那就是計(jì)算機(jī)并不能這樣持續(xù)不停地進(jìn)行平方運(yùn)算,原因在于存儲(chǔ)器中的存儲(chǔ)單元數(shù)量有限。也許你會(huì)想,既然我們只想要它計(jì)算從1到10000的整數(shù)的平方,那么等它算完10000的平方立刻把計(jì)算機(jī)關(guān)掉就好了。但你怎么會(huì)知道什么時(shí)候恰好算到了10000呢?計(jì)算機(jī)每秒鐘能進(jìn)行幾千次運(yùn)算,我們根本不可能及時(shí)地發(fā)現(xiàn)它計(jì)算到了我們想要的數(shù),并及時(shí)打斷它。怎么辦呢?很簡單,在編寫程序時(shí)就為它設(shè)計(jì)一套特殊的指令,使它在一定的時(shí)候自動(dòng)關(guān)機(jī)。比如編寫這個(gè)程序時(shí),我們就可以加入讓機(jī)器計(jì)算完1到10000的所有整數(shù)平方后自動(dòng)停機(jī)的指令。
說好了只分析簡單的程序,因此我們就不再涉及更復(fù)雜的指令了。計(jì)算從1到10000全部整數(shù)平方數(shù)的完整程序應(yīng)該是這樣的:
指令1、2與前面分析的簡單程序區(qū)別不大,完成這兩條指令,第8、9、10單元的數(shù)據(jù)變?yōu)椋?/p>
(8)1
(9)1
(10)12
指令3:求計(jì)算出第2和第6單元的數(shù)據(jù)之和,再將結(jié)果存入第2單元。第2單元發(fā)生如下變化:
這里可以很清晰地看到,指令3完成后,指令2中的一個(gè)地址發(fā)生了變化,這種現(xiàn)象的原因,我們會(huì)在后面進(jìn)行分析。
指令4:這條指令與前面簡單程序中的指令3一樣,要進(jìn)行條件轉(zhuǎn)移。這條指令的具體內(nèi)容是:如果第8單元的數(shù)小于第7單元的數(shù),則轉(zhuǎn)移到第1單元,如果情況正好相反,則進(jìn)行到下一指令(指令5)。我們可以看到,第8單元的數(shù)“1”的確比第7單元的“10000”小,所以轉(zhuǎn)移到第1單元,重復(fù)指令1。
指令1完成后:第8單元變?yōu)?/p>
(8)2
指令2完成后:第2單元變?yōu)?/p>
即將22的結(jié)果存入第11個(gè)單元。現(xiàn)在你知道為什么要提前完成指令3了嗎?是的,因?yàn)榈?0個(gè)單元已經(jīng)被占用,新計(jì)算出的22必須被送入下一單元。
完成指令1、2之后,我們得到了如下數(shù)據(jù):
(8)2
(9)1
(10)12
(11)22
指令3完成后,第2單元有了新變化:
這意味著計(jì)算機(jī)已經(jīng)做好將計(jì)算結(jié)果存入下一單元(即第12單元)的準(zhǔn)備。你一定已經(jīng)發(fā)現(xiàn),目前第8單元里的數(shù)據(jù)仍然小于第7單元里的數(shù)據(jù),所以執(zhí)行指令4的方式仍舊是回到第1單元。
計(jì)算機(jī)再次完成了指令1和指令2,我們得到的數(shù)據(jù)為:
(8)3
(9)1
(10)12
(11)22
(12)32
就像你看到的那樣,計(jì)算機(jī)會(huì)按照這個(gè)程序,不停地將平方數(shù)的計(jì)算進(jìn)行下去。等到第8單元中的數(shù)變成10000之后,這種計(jì)算才會(huì)停止。因?yàn)橛?jì)算機(jī)按照程序算完了從1到10000全部整數(shù)的平方數(shù),這時(shí)第8單元里的數(shù)已經(jīng)不再比第7單元里的數(shù)小,指令4不會(huì)再要求轉(zhuǎn)移至第1單元,而是進(jìn)行到下一指令,指令5的命令就是“停機(jī)”。
下面來看我們要分析的第二個(gè)程序,這個(gè)程序相對復(fù)雜一些:解方程組。當(dāng)然,這里所給出的仍舊會(huì)是一個(gè)被簡化了的程序,如果你有興趣,也可以將它完整地寫出來,這個(gè)方程組是這樣的:
解方程組,這并不難:
解出這個(gè)方程組,你至少也要花上幾十秒的時(shí)間,但計(jì)算機(jī)解幾千個(gè)這種方程組,最多只需要1秒鐘。
假設(shè)有下面一些方程組:
其中a、b、c、d、e、f、a'、b'、c'……都是已知的常數(shù)。
我們來看看讓計(jì)算機(jī)解這些方程組所用的相應(yīng)程序:
指令1:將第28單元與第30單元里的數(shù)據(jù)相乘,將結(jié)果存入第20單元,即將ce寫入第20單元。
接下來依此執(zhí)行指令2~6,完成后第20~25單元里的數(shù)會(huì)變?yōu)椋?/p>
(20)ce
(21)bf
(22)ae
(23)bd
(24)af
(25)cd
指令7:用第20單元里的數(shù)減第21單元里的數(shù),將結(jié)果存入第20單元,即將ce-bf寫入第20單元。
接下來依此執(zhí)行指令8~9,完成后第20~22單元里的數(shù)會(huì)變?yōu)椋?/p>
(20)ce-bf
(21)ae-bd
(22)af-cd
指令10和指令11要求完成除法:
并將結(jié)果記入卡片。
到此為止,第一個(gè)方程組中的未知數(shù)就全部解完了。
那么其他指令的作用是什么呢?本程序的第12~19單元是使計(jì)算機(jī)解第二個(gè)方程組的指令,其中指令12~17是要求計(jì)算機(jī)分別計(jì)算第1~6單元里的數(shù)與第19單元里的數(shù)之和,再將結(jié)果存回第1~6單元。指令17完成后,第1~6單元里的數(shù)據(jù)發(fā)生了如下變化:
(1)×34 36 20
(2)×33 37 21
(3)×32 36 22
(4)×33 35 23
(5)×32 37 24
(6)×34 35 25
指令18要求轉(zhuǎn)移到第1單元。
在接下來執(zhí)行指令的過程中,第1~6單元里的數(shù)據(jù)會(huì)發(fā)生什么變化呢?很簡單,前兩個(gè)地址的編碼不再是26~31,而是變成了32~37。也就是說,機(jī)器反復(fù)進(jìn)行著同樣的運(yùn)算,只是這一次是從第二個(gè)方程組各系數(shù)所在的第32~37單元選數(shù),而不是存貯著第一個(gè)方程組各系數(shù)的第26~31單元了。第二個(gè)方程組就這樣解完了,同樣的方法,機(jī)器繼續(xù)解第三個(gè)方程組,甚至更多的方程組,直到將要求解出的方程組全部解完為止。
分析上面兩個(gè)程序的過程讓我們清楚地意識(shí)到學(xué)會(huì)正確編寫程序的重要性。機(jī)器靠“自己”其實(shí)是什么都不會(huì)做的,它只會(huì)完成人交給它的程序。這些程序種類繁多,比如計(jì)算平方根的程序、計(jì)算對數(shù)的程序、計(jì)算正弦函數(shù)的程序、解高次方程的程序,當(dāng)然還有我們所提到過的下棋程序、翻譯程序等。一個(gè)明顯的特征是:人要求計(jì)算機(jī)做的工作越復(fù)雜,交給它的相應(yīng)程序就會(huì)越復(fù)雜。
計(jì)算機(jī)還有一個(gè)重要的功能,那就是編寫程序,但這需要人首先交給它一種“編程程序”,有了這種“編程程序”,計(jì)算機(jī)就能按照程序中的指令自動(dòng)編寫出相應(yīng)的程序來。編程工作通常是非常繁重的,這種編程程序的使用,能大大減輕人工編程所要承受的“沉重”負(fù)擔(dān)。(俄.別萊利曼)
聯(lián)系客服