數摞及運算方法
計算機中數的概念
漢語編程引入了數摞的概念 ,關於數摞我們應該從中國古老的算盤說起。
首先我們可以講,中國人最早發明了數字計算機即算盤,算盤的表達方式與現代計算機的表達方式非常接近。
探尋人類數位化的起源,大概要從結繩記事開始,人們把打繩結記為“1”,而未打繩結記為“0”。為方便起見,我們將一段繩子看作算盤的一個桿,打繩結視為算盤珠撥在上面,反之撥在下面。這樣就形成了一個二進制的算盤。
一個算盤珠只能表示兩種狀態,0或1,兩個算盤珠可以表示4種狀態;算盤珠全部撥下表示0,最右邊的珠子單獨撥上去表示1,左邊的珠子單獨撥上去表示2,兩個算盤珠都撥上去則表示3。這四種狀態分別表示為00,01,10,11。如果要表示更大的數則只有將算盤珠增多。三個算盤珠可以表示8種狀態,那么按2的n次方的算法依次類推分別為:
16,32,64,128,256,512,1024,2048,4096,16384,32768,65536,……。
計算機內部數的大小與算盤同樣有限,一般將其分為8位、16位、32位、64位等等。為了不至於將運算位取的太大,又能滿足於實際套用的要求,對於較早的系統將16位作為一個運算的基本單位,而對於進來的windows系統一般將32位作為一個運算的基本單位。一個16位的數可以表示65536種狀態,作為一個16位的正整數,可以從0~65535。但是作為一個有符號的數,則往往用16位最高位為1來表示這個數為負數,這時這個16位的數只能從-32768~+32767範圍。而一個32位的數可以表示4294967295種狀態, 作為一個32位的正整數,可以從0~4294967295。但是作為一個有符號的數,則往往用32位最高位為1來表示這個數為負數,這時這個32位的數只能從-2147483648~+2147483647範圍。對於一個16位的系統其單精度是16位,而雙精度是32位;對於一個32位的系統其單精度是32位,而雙精度是64位。
上述一個二進制的數可以表達一定的數值範圍,但它如何表達這個數的實際值呢?對於一個無符號數,我們可以按上述二進制的算盤記數的方法依次類推,對於16位數的每一種狀態找到其從0~65535的對應值;而對於32位數的每一種狀態找到其從0~4294967295的對應值。但對於有符號數來說就不能簡單地套用這種辦法。在有符號數的二進制表示中,我們分別引入原碼、反碼和補碼三種概念。為了簡單起見,我們以8位數來說明有符號數三種編碼的表示方法。
帶符號數的表示法
一個數可用其最高位來表示符號,正數的最高位為0,負數的最高位為1,其餘位仍然按正常方法表示數值,這種表示方法叫做原碼錶示法。如:
原碼錶示簡單易懂,而且與機器的真值轉換方便。但若是兩個異號數相加(或兩個同號數相減)就要做減法。為了把上述運算轉換為加法運算就引入了反碼和補碼的概念。
正數的反碼錶示與原碼錶示相同,最高位為符號位,用“0”表示正,其餘位為數值位。如:
符號位 二進制數值
( +4) = 0 0 0 0 0 1 0 0
( +31) = 0 0 1 1 1 1 1 1
(+127) = 0 1 1 1 1 1 1 1
而負數的反碼錶示,即為它的正數的按位取反(含符號位)。
符號位 二進制數值
( +4) = 0 0 0 0 0 1 0 0
( - 4) = 1 1 1 1 1 0 1 1
( +31) = 0 0 0 1 1 1 1 1
( - 31) = 1 1 1 0 0 0 0 0
(+127) = 0 1 1 1 1 1 1 1
(- 127) = 1 0 0 0 0 0 0 0
( +0 ) = 0 0 0 0 0 0 0 0
( - 0 ) = 1 1 1 1 1 1 1 1
8位二進制數的反碼錶示有以下特點:
1. “0”有兩種表示法。
2. 8位二進制反碼所能表示的數值範圍為+127~ -128。
3. 當一個有符號數用反碼錶示時,最高位為符號位。當符號位為“0”(即正數)時,後面的七位為數值部分;但當符號位為“1”(即負數)時,後面幾位表示的不是此負數的數值,一定要把它們按位取反,才表示它的二進制值。
二進制表示的另一種方式為補碼方式。正數的補碼錶示與原碼錶示相同,即最高位為符號位,用“0”表示正,其餘位為數值位。如:
符號位 二進制數值
( +4) = 0 0 0 0 0 1 0 0
( +31) = 0 0 1 1 1 1 1 1
(+127) = 0 1 1 1 1 1 1 1
而負數的補碼錶示即為它的反碼,且在最後位(即最低位)加1。如:
符號位 二進制數值
( +4) = 0 0 0 0 0 1 0 0 原碼
( - 4) = 1 1 1 1 1 0 1 1 反碼
( - 4) = 1 1 1 1 1 1 0 0 補碼
( +31) = 0 0 0 1 1 1 1 1 原碼
( - 31) = 1 1 1 0 0 0 0 0 反碼
( - 31) = 1 1 1 0 0 0 0 1 補碼
(+ 127) = 0 1 1 1 1 1 1 1 原碼
(- 127) = 1 0 0 0 0 0 0 0 反碼
(- 127) = 1 0 0 0 0 0 0 1 補碼
( +0 ) = 0 0 0 0 0 0 0 0 原碼
( - 0 ) = 1 1 1 1 1 1 1 1 反碼
( - 0 ) = 1 0 0 0 0 0 0 0 補碼
8位帶符號的補碼錶示有以下特點:
1.(+0)= (- 0)= 00000000
2. 8位二進制補碼所能表示的數值為:+127~-128
3. 一個用補碼錶示的二進制數,最高位為符號位,當符號位“(即正數)時,其餘七位即為此數的二進制值;但當符號位“1”(即負數)時,其餘幾位不是此數的二進制值,把它們按位取反,且在最低位加1,才是它的二進制值。當負數採用補碼時,就可以把減法轉換成加法。例如:
64 –10 =64+(-10)=64+[10]補
+64=01000000
10=00001010
[-10]補=11110110
於是
0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0
- 0 0 0 0 1 0 1 0 + 1 1 1 1 0 1 1 0
———————— ————————
0 0 1 1 0 1 1 0 [ 1] 0 0 1 1 0 1 1 0
自然丟失
一個算盤的位數是有限制的,在做運算時最高位將自行丟失,故做減法與補碼相加的結果是相同的。同樣我們可以將這種表示法擴展到16位以至32位。計算機中在許多情況下都是用二進制補碼的方式表示數值的。漢語程式語言在大部分情況下也用二進制補碼錶示數值。
補碼的巧妙套用使計算機中的加法與減法一致,這無疑在簡化計算方法,提高計算機運行效率起了很大的作用。
如果把每個小算盤看作一位數,那么它能表示數的範圍是0~15。在我們習慣的十進制表示法中一位數字只能表示0~9,從10開始需用兩位以上的數字表示。若想用一位數來表示十以上的數字,則可利用那些最常用的、使用最方便的字元。在十六種狀態中,零至九仍用阿拉伯數字0~9表示,而十至十五則用英文字母A~F表示,這就是十六進制表示法。這樣上面的每一個小算盤的十六進制表示法就是:
從單獨一個小算盤很容易看出十六進制與二進制的對應關係。巧妙的是四位二進制數正好是一位十六進制數。這樣在識別一個十六進制數代表的二進制狀態時,可以按位四位一組進行二進制變換,且變換過程中不會象十進制轉換為二進制那樣,轉換一位而影響其他位。
為了便於理解我們將一個四位小算盤三種數制的對應關係列出:
以後進行二進制與十六進制之間的互相轉換,可以根據上面算盤的對應關係來完成。但要進行多位的十進制轉換則必須進行計算。
有趣的是中國傳統的算盤不僅可以進行十進制計算,同時還可很方便的完成十六進制計算。下面把傳統算盤的十六進制表示法列出供大家思考。
算盤的一排珠子可以表示從0~15,即十六進制的一位,也是中國傳統十六兩制的一位,可見成語中“半斤八兩”表示的是二者相等,而不是差不多。
我們可以把一根算盤桿看作為計算機的四位,而兩根算盤桿看作為計算機中的八位,專業術語稱為“位元組”,當以後分析計算機數據結構時你可以將兩根算盤桿想像為一個位元組。那么上面的算盤正好是計算機中一個64位數。
漢語編程為了提高運算速度、最佳化結構、方便記憶,借鑑中國古代數學算籌的思想,採用了“數摞” 這一特殊方式,將參與運算的數據如同一個個算籌或算盤在計算機記憶體中有序地摞起來。在運算過程中,自動把摞頂層參與運算的數據刪除,並將運算結果重新放回到頂層。這種累加器總是在頂端暫存器的操作方式,實踐了無限暫存器這一新的計算機理論。數摞是漢語程式設計語言中的一個重要方式,,本章將著重介紹其具體操作及與之密切相關的算術運算和邏輯運算。
數摞的概念及表示方法
數摞是漢編程式中獨有的概念 ,它是在記憶體中開闢出的一個空間,它不僅是漢編程式運行中數據處理的場所,也是數據臨時存儲的場所,還是各模組間參數傳遞的場所。數摞結構的引入既統一了程式中各參數的臨時存儲場所和格式,也讓程式設計師能夠同步跟蹤並調試程式的運行。而在C語言中所有這些工作只能交給編譯器,一旦出現錯誤,調試工作只能從零開始。
你可以把計算機想像為一個機械的計算員,當它進行計算時僅有我們上面提到的算盤,而沒有紙和筆。在進行大量的數據運算時,為了提高計算速度和便於記憶,最好的辦法就是將算盤有序擺放,比如將算盤摞起來。為了保證在一定的空間可以放足夠多的算盤,就將參加運算的數據以及結果的算盤都摞放起來。每次總是將參與計算的算盤拿走然後再將表示結果的算盤摞在頂層。例如進行一個最簡單的加法運算3+4,我們先將表示3的算盤摞在頂上:
3
:
:
橫線表示底線,在3和底線之間可能還有以前摞上去的算盤。然後再將表示4的算盤摞在頂上:
4
3
:
:
有了兩個數後就可以做加法運算,其結果為7。這時參與運算的3和4已經沒有用處就將它們移去,再把結果的7摞在頂上。
7
:
:
並非只有用移動盤的方法才能解決問題,而修改每個算盤中的內容更簡便易行。在計算機內實際也只是修改相應記憶體的數值,而不能把這些記憶體地址搬來搬去。為了便於表達,我們稱這個摞數的地方為“數摞”。數摞在表示數的時候,總是將最後輸入的數放在數摞頂層,而前面輸入的數向下順移。有了數摞的概念,以後我們都按上面的這種方法來進行所有的計算。計算機的運算往往是連續的,前面計算的結果可能是後面運算所需要的參數。如計算(3+4)*5則按上面的方法先將3摞在數摞頂上,再將4摞在數摞頂上:
4
3
:
:
做完加法後將4和3去掉,並將7摞在數摞頂上:
7
:
:
然後再將5摞在數摞頂上:
5
7
:
:
最後做完乘法後將5和7去掉,將乘法的結果35摞在數摞的頂上:
35
:
:
我們剛才計算的是(3+4)*5,但是操作的順序卻沒有按這個式子進行,而是3 4 + 5 * 。這種表示並不奇怪,無論做什麼樣的計算首先應該有被計算的數據,用(3+4)*5隻是一種習慣,叫做中綴表示法。而用3 4 + 5 * 的表示方法叫做後綴表示法,即將運算符號放在參與運算的兩個數的後面。採用後綴表示法也是一個習慣問題,它可以省去代表許多優先權的符號,更符合人類統籌安排事務的行為方式,比如在建築過程中,我們總是首先設計好圖紙,準備好建材,最後才開始施工。漢語正是使用這種表達方式,把中國古代數學文明與現代計算機編程技術巧妙地結合在一體。
漢語程式設計始終利用數摞來完成常規的運算,所以我們必須弄懂數摞的概念,並熟練地運用於程式設計之中。
數摞操作
一個人說話是要表達自己的意圖,為了達到這一目的,在說話時可能會參雜許多不可缺少的“廢話”,舍此,這段話可能就“不像話”了。程式設計也是如此,如彙編語言中要頻繁的保護暫存器,高級語言中卻要不斷的進行變數操作。在漢語程式語言中,出現最多的“廢話”就是數摞操作,然而正由於這些“廢話”才使我們的程式設計變得更為精巧和生動。
在標準的漢語程式設計中所建立的數摞均以32位為基本單元。我們可以將一層想像成為一個具有32個桿和珠的算盤,每一個數都是由這種32位為基本單位的算盤來表示的。漢語編程操作與運算過程中的數據都是從數摞上取得,而操作結果也將放在數摞的頂上。這樣顯然帶來一個問題,有的時候操作的結果並不一定是後面操作所需要的運算元,或者即使是運算元,但按後面操作的要求其順序不對,或者後續的操作只需要部分的結果,使得我們不得不將數摞上的數據進行必要的調整以及複製。在漢語程式語言中提供了一系列的數摞操作算符,以便在程式設計中對數摞上的數據進行適當的調整。
數摞操作是漢語程式設計中最有趣,最巧妙的一個環節,使用極為頻繁,讀者一旦熟練掌握,到那時就可隨心所欲編寫漢語編程了。
數摞的交換
現在你來充當計算操作員,計算過程由指令員來指揮。指令員要做一個算術運算20-3*4,按照算術運算的優先規律應該先乘除後加減。所以指令員先將兩個要相乘的數告訴你,由你按順序將這兩個數放入數摞:
4
3
接下來指令員又發出乘法指令,你計算出3 *4的結果,並將數摞上的3和4去掉,然後將結果12放入數摞:
12
指令員又將20告訴你,你隨即將20放入數摞:
20
12
這時如果指令員發出減法的指令就出現問題了,因為減法沒有交換規律,按規律必須是前面的數減去後面的數。在我們數摞上前面的數就是先進入的數,如果直接進行減法操作,就變成了12-20,為了解決這類問題,引入了一些數摞操作符。象上面的減法問題只要將兩個數進行一次交換再執行減法就可以了。我們用符號“↑↓”表示交換操作。這樣指令員在發出減法指令以前就必須發出“↑↓”指令,你就將數摞上數據的順序交換一下,變成:
12
20
然後指令員再發出減法指令,你在做完減法後就可以將12和20去除,並將計算結果8放入數摞:
8
這個過程用漢語程式語言可以表述下面的形式:
3 4 * 20 ↑↓ -
以上只是為了說明問題舉了一個例子,當然對於這樣一種簡單的計算完全可以寫成另一種簡化的形式
20 3 4 * -
我們放物品並不一定都是豎向摞置,有時要橫向碼放,如書架上的書基本上是橫向碼放的。為了表達方便,我們在表示數摞時常常也用橫向方式來表示數摞里的狀態。我們寫文章時習慣從左至右,如果寫的是數就進入數摞保存起來,先進入數摞的就在左邊而後進入的就在右面。用橫向法表示數摞時則記憶為右邊的數在上,左邊的數在下。如1 2 3 則表示為:
3
2
1
為了表達方便,我們還引入了數摞操作表述符號“―――”,並將操作前的數摞狀態寫在“―――”的左邊,操作後的數摞狀態寫在右邊,規範的寫法應該為三個“―”,請讀者養成良好的習慣。數摞上的數可以是一些代號,如“n1”、“n2”等等。如上面的“↑↓”操作,就表示為:
↑↓ ( n1 n2 ―――n2 n1 )
它代表
n1 n2 ↑↓ n2 n1
而對於“+”操作就表示為:
+ ( n1 n2 ―――n3 )
其中n3是n1與 n2之和。
了解了以上的基礎知識,就可以進行數摞操作的練習了。在漢語編程系統中,系統提示符為“★”,表示操作的結束。在提示符“★”下的游標處就可以直接輸入數值,並通過一些數摞的顯示操作去查看數摞,如:
1 2 3 ★…
上面的描述中“<回車>”是指從鍵盤上鍵入[←┘Enter]鍵。提示符“★”後面有幾個點“.”就表示當前數摞有多少個數。下面執行“看數摞”命令:
看數摞 [3]1 2 3 ★…
“看數摞”命令能顯示當前數摞上仍保留的數。“[3 ]”表示當前數摞上有三個數。
+ ★..
看數摞 [2] 1 5 ★..
↑↓ ★..
看數摞[2] 5 1 ★..
需要注意的是,數摞交換操作符“↑↓”只對數摞頂項和次頂項進行交換操作。我們在數摞上再加一個數,然後執行交換操作:
2 ★…
看數摞 [3] 5 1 2 ★…
↑↓ ★…
看數摞 [3] 5 2 1 ★…
數摞的複製
許多情況下為了保證參加操作的數據仍然保留在數摞上,我們有必要對數摞上的數進行複製。在漢語編程中,對數摞進行複製的操作符是“♂”,其功能是對數摞頂層的數進行複製並將複製的數放在數摞頂層。
看數摞 [3] 5 2 1 ★…
♂★....
看數摞 [4] 5 2 1 1★....
操作符“♂”比較形象,圓圈代表數,向上的箭頭代表向頂上複製,執行“♂”操作後的數摞狀態為:
♂ ( n ―――n n )
“♂”的用途比較廣,下面還是用“平方”的例子加以說明:
編 平方 ♂ * 。
該程式的運行體為“♂ *”。執行程式前,我們先給出一個參數n,當程式執行時,先複製一個n,將兩個n相乘,即得到n的平方的結果。
複製次摞層
次摞層是從數摞頂層向下第二層,也是數摞第1項(以0基計算,數摞頂層為第0項,次摞層為第1項,依此類推)。次摞層的複製採用“∽”操作符:
看數摞 [3] 5 3 1 ★…
∽★....
看數摞 [4] 5 3 1 3 ★....
該例將數摞第1項3複製到數摞頂層作為第0項。
執行“∽”操作時數摞的狀態為:
∽ ( n1 n2 ―――n1 n2 n1 )
用橫向比較法來看該符號,此圖形好象繞過了摞頂的數而複製了第二項數據。
複製任意項
當我們需要對數摞上的任意一項進行複製時,可採用“§”操作符。使用該操作符時需指定參數,即指明將第幾項複製到數摞頂層。
看數摞 [4] 5 3 1 3 ★....
2 § ★.....
看數摞 [5] 5 3 1 3 3 ★.....
該例將數摞的第2項(即3)複製到數摞頂層作為第0項。
使用該操作符同樣需注意,前面的參數表示數摞的項數,這個項數同樣以0基方式計算,如2表示數摞的第二項,即數摞從上往下第三層。
技巧:參照“♂”、“∽”可知:
0 § 等價於 ♂ ;1 § 等價於 ∽
數摞的旋轉
在漢語編程過程中,有時需要將數摞上的三個數進行輪轉,即將第三層的數放到數摞頂上,並將其他兩個數向下順移。這時我們採用“∴”操作符:
看數摞 [5] 5 3 1 2 4 ★.....
∴★.....
看數摞 [5] 5 3 2 4 1 ★.....
清屏後可以再舉一例:
1 2 3 ★...
看數摞[3]1 2 3 ★...
∴★...
看數摞[3]2 3 1 ★...
執行“∴”操作時的數摞狀態為:
∴ ( n1 n2 n3―――n2 n3 n1 )
反向旋轉摞頂三項
有了數摞旋轉的概念,就很容易理解數摞的反向旋轉。它是將數摞頂層的數放到數摞第三層,並將原來第二層和第三層的數向上順移。這時我們採用“∵”操作符:
看數摞 [5] 5 3 1 2 4 ★.....
∵★.....
看數摞 [5] 5 3 4 1 2 ★.....
清屏後可以再舉一例:
1 2 3 ★...
看數摞[3]1 2 3 ★...
∵★...
看數摞[3]3 1 2 ★...
執行“∵”操作時的數摞狀態為:
∵ ( n1 n2 n3―――n3 n1 n2 )
剔出任意項
雖然我們可以複製數摞上的任意項,但有時還有必要只將數摞上的任意項剔出來放在數摞的頂上。這時我們可以採用“√”操作:
看數摞[2]2 3 ★..
4 5 ★....
看數摞 [4]2 3 4 5 ★....
1 √ ★....
看數摞[4]2 3 5 4 ★....
2 √★....
看數摞 [4]2 5 4 3 ★....
3 √★....
看數摞 [4]5 4 3 2 ★....
執行“√”操作時的數摞狀態為:
√ ( nn……n1 n0 n ―――nn-1 ……n1 n0 nn )
技巧:參照“∴”知:
2 √ 等價於 ∴
0 √ 是空操作
去除操作
在程式設計過程中,數摞上的有些數我們並不需要,為了不影響以下的操作,不得不將其刪除。這時可以採用“♀”操作符:
看數摞[3]2 3 1 ★...
♀★..
看數摞[2]2 3 ★..
該例使用去除操作符將數摞頂層的數刪除。
注意,該操作符只能刪除當前數摞頂層即第0項的數。
執行“♀”操作時的數摞狀態為:
♀ ( n ――― )
雙精度數摞操作
雙精度數摞操作是把普通數摞的兩層當作一個整體來處理,操作方式與單層基本相同,主要包括內容有:雙↑↓、雙♂、雙∽、雙♀ 。
漢語編程中的運算方法
前幾節我們主要對漢語程設計語言做了基本的介紹,並從實用的角度介紹了一些基本的操作,對於算術運算只是從套用的角度簡單地做了嘗試。本節我們將著重地討論漢語程式設計語言的算術運算和邏輯運算。
算術運算
對於算術運算,我們從數的加減運算、乘除運算和浮點運算三個方面來講述。
甲、數的加減運算
說到加、減、乘、除運算,大家肯定認為國小就學過加、減、乘、除,沒必要再學了。其實編寫電腦程式用到的主要還是古老的算術知識,高中、大學學到的許多高等數學知識不能被計算機直接解析。漢語程式設計語言的加、減、乘、除運算都是將數摞上的兩個32位的數進行運算,同時“吃掉”參與運算的兩個頂層數,將運算的結果放回數摞的頂層。
這樣的運算只能對有符號數-2~+2-1(-2147483648~2147483647)之間的數進行運算,且運算結果也不能小於-2147483648和大於2147483647。一般情況下這個範圍內的數是夠用了,那如果不夠用怎么辦呢?在漢語程式設計語言中,各種運算和操作都是通過數摞進行的,數摞的每一層為一個32位的數,要表示更大的數可以有數摞的多層來表示。如果用數摞上的兩層來表示一個數,我們就稱這個數為雙精度數,一個雙精度數表示有符號數的範圍就為:-2~+2-1。
對用數摞上的兩層來表示的數,不能簡單的用“+”、“-”來完成,而套用“雙+”、“雙-”來完成,且運算結果也占數摞的兩層。下面是加減運算實際操作實例:
2 8 <回車>★.. (註:向數摞放了兩個數:2和8)
看數摞<回車> [2] 2 8 ★.. (註:用“看數摞”查看數摞的狀態)
+ 看數摞<回車> [1] 10 ★. (註:經過“+”運算後數摞的狀態)
說明:最後數摞上的“10”就是“2+8”的結果。經過“+”運算後,將數摞上的“2和8”去掉,留下結果“10”。加法運算的數摞狀態為:
+ ( n1 n2 --- n3 )
11<回車>★.. (註:繼續向數摞放進一個數11)
看數摞<回車>[2] 10 11★..
- 看數摞<回車>[1] –1★ .
說明:最後數摞上的“-1”就是“10-11”的結果。經過“-”運算後,將數摞上的“10”和“11”去掉,留下結果“-1”。減法運算的數摞狀態為:
- ( n1 n2 --- n1 - n2 )
10 9 1 5 <回車>★....
看數摞<回車> [4] 10 9 1 5 ★....
雙+ 看數摞<回車> [2] 11 14 ★..(註:經過“雙+”後數摞上留下的運算結果)
10 <回車>★...
看數摞<回車> [3] 11 14 10 ★...
雙+ 看數摞<回車> [1] 21 ★. (註:將10和11相加,丟失14)
3<回車>★..
看數摞<回車> [2] 21 3 ★..
雙+ 看數摞<回車> 數摞已空!★
3 6 9 5 8 15<回車>★......
看數摞<回車> [6] 3 6 9 5 8 15 ★......
雙+ 看數摞<回車> [4] 3 6 17 20 ★....
由該例可知,“雙+”運算是對數摞頂上的4個數進行交叉運算,如果對兩個數進行“雙+”運算,則數摞為空;如果數摞上只有三個數,只能對第0項和第二項進行相加運算,而丟掉第一項;如果數摞上的數多於4個,則只對摞頂4個數進行交叉運算,其它的數不進行運算。雙+數摞狀態為:
雙+ ( d1 d2 --- d3 )
同樣道理,我們也可以進行“雙-”運算,大家可以自己練習,這裡不再贅述。
乙、數的乘除運算
漢語編程中有符號數的乘法運算與加法運算相同,操作前數摞上有兩個有符號數,當執行完“*”後,參與運算的數摞被“吃掉”,留下兩個數相乘的積。如:
2 8 <回車>★.. (註:向數摞放進兩個數:2、8)
看數摞<回車> [2] 2 8 ★.. (註:用“看數摞”查看數摞上的狀態)
* 看數摞<回車> [1] 16 ★. (註:經過“*”運算後數摞上的的狀態)
說明:最後數摞上的“16”就是“2*8”的結果。經過“*”運算後,將數摞上的“2”和“8”去掉,留下結果“16”。乘法運算的數摞狀態為:
* ( n1 n2 --- n3 )
n3是n1與n2的乘積,n3是32位,如果n1與n2的乘積超出-2147483648~2147483647的範圍,其結果不可預測。由於在-2147483648~2147483647範圍內的數已經足夠使用,因此不用考慮數據溢出的問題。
除法與乘法是相對應的,漢語程式語言中的除法操作也會遇到有符號和無符號、單精度和雙精度以及混合運算等問題。另外在除法運算時還存在商數的取整問題。在漢語編程中為方便計算機的運算,採用了向下取整的方法。如按向下取整的方法做
-7÷4=-2 余 +1
而用向零取整的方法得出上面的結果後還必須加1才對,在整數運算中採用了向下取整,則應考慮餘數的符號必須與除數相同。總之應該為:
商*除數+餘數=被除數
以上是整數運算中需要了解的基本知識,在漢語程式設計語言的程式設計中可以通過各種除法運算詞來完成不同類型的除法運算。如:
/ ( n1 n2 ――― <商> )
數摞上留下n1除以n2的帶符號32位的下整商。
求餘數 ( n1 n2 ――― <餘數> )
數摞上留下n1除以n2的餘數,餘數具有與n2相同的符號或者為零。
/余商 ( n1 n2 ――― <餘數> <商> )
數摞上留下n1除以n2的餘數和帶符號的下整商。餘數取除數的符號或為零。
丙、浮點數運算
漢語程式設計語言整合了浮點數、整數的處理的問題。所謂浮點數也是計算機採用的一種表示法,它把一個數的整數部分和小數部分分開表示。
採用浮點數表示法有很多的優點。在相同設備的情況下,浮點數能表示數的範圍比定點數表示法要大,給程式設計帶來方便;浮點計算中的數若採用規格化表示,則其精度較高,相對誤差有限;由於能表示的數的範圍很大,一般來說可以不必擔心“溢出”問題。
漢語編程中的浮點數運算也就是將兩個浮點數進行加、減、乘、除運算,運算後,按五舍六入的法則將小數點後按預先的定義保留若干位小數。定義小數位的格式為:n 位小數,如在漢語編程編譯器下進行下列運算:
2.2 8.5<回車> ★.. (註:向數摞放了兩個數:2.2 8.5)
+ 顯<回車> [1] 10.70 ★ (註:經過“+”運算後,用“顯”這個詞顯示運算的結果“10.70”並將結果刪除 )
3 位小數<回車>★ (註:定義需要保留的小數的位數)
2.523 3.412 <回車>★..
+ 顯<回車> [1] 5.935 ★
4 位小數<回車>★
8.599 2.314 <回車>★..
- 顯<回車> [1] 6.2850 ★
漢語編程浮點運算在保留小數位時要遒循五舍六入的規則,這與我們習慣的四捨五入不同,要注意區別對待。如進行如下運算:
4 位小數<回車>★
2.03695 0.12362 + 顯<回車>2.1606★
3.22236 2.98756 * 顯<回車>9.6270★
總之,漢語編程中的算術運算與通常的數學算術運算基本一樣,所不同的是它參與運算的數必須是同一類型,且是通過數摞來進行運算。
邏輯運算
邏輯運算要比算術運算簡單的多,因為其參與運算的數和運算結果按位來看都只有兩種狀態:0和1。在這裡0和1不是表示具體的數值,而表示兩種不同的邏輯狀態(一般用0表示假,1表示真),邏輯運算中的最基本的運算有三種,即與、或、非三種,也叫邏輯乘、邏輯加、邏輯求反。
甲、 邏輯乘法 (與)
邏輯乘法運算就是將兩個基本命題用“與”這個系統詞連線起來構成一個複合命題。
如基本命題:
一個星期有七天
一天有二十四小時
用“與”連線起來的複合命題:
一個星期有七天 與 一天有二十四小時
由這樣的複合命題得出的結果(邏輯積),仍然是命題,重要的一點是要搞清邏輯積的真假是怎樣由命題的真假來決定。總結邏輯乘法(與)的運算規則如下:
1.如果兩個基本命題都是假的,它們的邏輯積也是假的。如:
3比2小 與 3比5大。
很明顯“3比2小”是假的,“3比5大”也是假的,所以邏輯積也是假的。
2.兩個基本命題中有一個是假的,則邏輯積也是假的。如:
3比2大 與 3比5大
“3比2大”是真的,“3比5大”是假的,所以邏輯積也是假的。
3.兩個基本命題都是真的,則邏輯積也是真的。如:
3比2大 與 3比5小
“3比2大”是真的,“3比5大”也是真的,因此邏輯積也是真的。
如果用A和B表示兩個基本命題,可以將邏輯積寫成AB(也可寫成AΛB或A·B)總結以上三點,可以將其列成一個表。如下:
A | B | AB |
0 0 1 1 | 0 1 0 1 | 0 0 0 1 |
我們一般把這個表叫做命題A、B的真值表。總結這個表,可以得出邏輯乘法運算規則是:有一命題為假邏輯積則為假,全部命題為真時邏輯積才為真。
乙、邏輯加法 (或)
邏輯加法運算就是將兩個基本命題用“或”連線起來構成複合命題。由這樣的複合命題得出的結果就是邏輯和,邏輯和的值為“0”或“1”,全由組成這個複合命題的基本命題來決定,總結邏輯加法(或)運算的運算規則如下:
1.兩個基本命題都為假,則邏輯和也為假。如:
9小於5 或 9小於1
由“9小於5”和“9小於1”都是假命題,所也邏輯積就為假。
2.兩個基本命題有一為真,則邏輯和就為真。
3.兩個基本命題都為真,則邏輯和也為真。
若用A和B表示兩個基本命題,總結以上三點可以得出邏輯和(A+B)的真值表如下:
A | B | A+B |
0 0 1 1 | 0 1 0 1 | 0 1 1 1 |
丙、邏輯求反運算 (非)
邏輯求反運算就是將一個基本命題用“非”這個系統詞連線起來組成複合命題。邏輯求反運算的結果完全由這一個基本命題來決定。由於是“求反”運算,所以很顯然也看出,如要基本命題為真,則結果就應為假,如果基本命題為假,求反後,結果就應為真。
若用A表示這個基本命題,求反後的結果就應表示為_A,則邏輯求反運算的真值表可表示為:
A | _A |
0 1 | 1 0 |
丁、邏輯表達式
邏輯表達式就是用與、或、非等符號將基本命題連線起來的複雜的複合命題。如果用A、B、C分別表示三個基本命題,則(A+B)·C就是一個邏輯表達表,其意義是:A和B相或,結果再和C與。因此表達式(A+B)·C也可以表示為:(A或B)與C。其運算規則仍然遵循與、或、非的運算規則,其運算結果仍只有兩種“0”或“1”。
若在同一邏輯表達表中同時有“與”運算、“或”運算和“非”運算,則按先“非”,後“與”,再“或”的規則省去括弧。如“(AB)+(CD)”可寫成“AB+CD”,而“(A+B)·(C+D)”不能寫成“A+B·C+D”。
邏輯表達式的基本類型有以下幾種:
1.“與或”表達式 在這種表達式中,各項以“與或”形式出現。
例如: F=AB+CD
2.“或與”表達式 在這種表達式中,各項以“或與”形式出現。
例如: F=(A+B)(C+D)
3.“與非”表達式 在這種表達式中,各項以“與非”形式出現。
F=AB·_CD |
例如:
4.“或非”表達式 在這種表達式中,各項均以“或非”形式出現。
F=A+B·C+D |
例如:
5.“與或非”表達式 在這種表達式中,各項均以“與或非”形式出現。
F=AB+CD |
例如:
總之,一個邏輯表達式有很多種形式,也可能很複雜。因此,通常要對邏輯表達式進行簡化以取得最簡表達形式。
漢語編程中的邏輯運算
有了以上的邏輯學的基礎知識,接下來我們討論漢語程式設計語言的邏輯運算。在漢語編程中我們可以用定義詞來建立命題。如在漢語編程編輯器中定義如下內容:
編 真 1 。
編 假 0 。
編 3比5大 假 。
編 3比2小 假 。
編 3比2大 真 。
編 3比5小 真 。
編輯完後保存為“C:\邏輯運算.chp”,然後打開漢語編程編譯器裝載該程式。裝載完成後,可以在漢語編程系統下進行邏輯“與”操作。
3比5大 3比2小 與★.
顯 0 ★
漢語編程邏輯運算與加、減、乘、除運算一樣採用後綴表示法來表示。該例說明兩個假命題相與的結果為假。
3比5大 3比2大 與★.
顯 0 ★
結果說明一個假命題、一個真命題相與結果也為假。
3比5小 3比2大 與★.
顯 1 ★
結果說明兩個真命題相與其結果為真。
進行完“與”操作後,我們再利用剛才所編的程式來進行邏輯“或”運算。同樣需要裝載“邏輯運算.chp”這個程式,若剛才裝載後還沒有退出漢語編程系統,就不需要再裝載了。
3比5大 3比2小 或★.
顯 0 ★
結果說明兩個假命題相或的結果為假。
3比5小 3比2小 或★.
顯 1 ★
結果說明一真一假兩個命題相或的結果為真。
3比5小 3比2大 或★
顯 1 ★
結果說明兩個真命題相或的結果為真。
進行完“與”和“或”的邏輯運算,我們再來看一下邏輯“非”的運算。同樣在裝載了“邏輯運算.chp”的情況下:
3比5大 非★.
顯 -1 ★
結果說明假命題經過“非”運算後,其結果為真。
3比2大 非★.
顯 -2 ★
結果說明真命題經過“非”運算後,結果為假。
到這裡,大家可能會問,為什麼對0進行“非“運算結果為-1,而對1進行“非“運算其結果為-2呢?
在經過上面一系列的操作後,大家應該知道,邏輯運算的操作也都是在數摞上進行的,操作前數摞上必須有參與邏輯運算的參數,操作後數摞上保留有邏輯運算的結果,在進行邏輯運算時,是按位進行運算的。如果數摞上的每一層都是一位的數,而不是32位的數,那么這時
1 非=0 0非=1
但是在漢語程式設計語言中數摞上的每一層數都是一個32位的數,所以在按位進行邏輯操作時,用1表示的邏輯真在數摞中只占用了一位,即:00000000000000000000000000000001,在進行“非”操作後,將32位的數“1”按位求反,結果就成為:11111111111111111111111111111110,這個數作為二進制補碼的有符號數就顯示為-2。
因此,在漢語編程中為了使邏輯運算更為適用,就規定對於一個32位的數,0為邏輯假,而非0為邏輯真。對於一個標準的漢語編程系統給出的邏輯真則為-1,這樣我們最將前面程式中定義的邏輯真改為:
編 真 -1 。
這樣在做上面的邏輯操作時,給出的邏輯真結果就是-1,而不是1。它保證了32位數中所有位都為1。