Prolog/數學、函式和等式
本節介紹如何在 prolog 中使用數學,使用函式和等式。
Prolog,像任何其他程式語言一樣,對數字有表示。數字像常量一樣使用,並像計算機上的任何地方一樣表示,以下是謂詞中處理數字的有效方式
a(12, 345). a(A) :- b(A, 234.3). a(345.3409857) :- b(23476.923804).
要對數字執行數學運算,我們需要函式。要將數學運算的結果儲存在變數中,我們需要更仔細地檢視等式。
到目前為止,謂詞始終代表簡單的真或假。謂詞 a(A, B) 是真還是假,取決於 A 和 B 的值。函式是表示值的謂詞。例如,sin() 謂詞是一個函式。sin(0) 代表值 0,sin(1) 代表值 0.841471。函式可以在任何可以使用數字或常量的地方使用,在查詢、謂詞和規則中。例如,如果事實 p(0). 位於您的程式中,則查詢 ?- p(sin(0)). 將與其統一。
以下常見的數學函式內置於大多數 Prolog 實現中
| 函式 | 示例 | 結果 |
|---|---|---|
| + | 2 + 3 | 5 |
| - | 36 - 5 | 31 |
| * | 4 * 3 | 12 |
| / | 36/5 | 7.2 |
| ^ | 4 ^ 2 | 16 |
| sin | sin(3) | 0.14112 |
(待補充表格)
請注意,函式本身無法計算。查詢 ?- sin(3). 將失敗,因為 sin() 被實現為函式而不是謂詞。
函式和謂詞之間的區別之一是,謂詞的含義(或定義)通常由您自己定義,在您的程式中。當您使用 sin() 之類的函式時,它們已經在您的 prolog 實現中定義了。換句話說,prolog 不會在您的程式中找到定義,而是在其 內建 謂詞庫中找到。您可以建立自己的函式,但您通常不需要這樣做。
有幾種等式,含義略有不同。這裡我們只看 = 運算子和 is 運算子。首先,看一下
?- A is 36/5.
此查詢將數學運算 36/5 的結果分配給變數 A。因此 Prolog 將回答
A = 7.2
這個想法可能來自其他程式語言。然而,= 運算子非常不同。它不求解右側,而是將其保留為公式。所以你會得到這個
?- A = 36/5. A = 36/5
Prolog 不會將運算的結果分配給變數 A,而是將運算分配給 A,而不進行求解。
您可以在查詢中看到相同的情況。如果您詢問
?- (31 is (36-5)).
您將得到“是”,因為 (36-5) 已被求解。但是,如果您詢問
?- (31 = (36-5)).
您將得到“否”,因為 Prolog 會將數字 (31) 與公式 (36-5) 進行比較,而不是與求解公式的結果進行比較。
is 運算子專門用於數學函式。左運算元必須是變數,右運算元必須是所有變數都已例項化的數學函式。= 運算子用於變數的統一,並且可以用於任何兩個運算元(儘管如果兩個運算元不同,並且無法透過以特定方式例項化變數來使其相同,則它將失敗)。
Prolog 知道許多其他比較兩個項或例項化變數的方法,但就目前而言,這兩個就足夠了。在處理函式時,我們幾乎總是使用 is 運算子。
現在我們已經瞭解了函式和等式,我們可以開始用數學進行程式設計。
plus(A, B, C) :- C is A + B.
此謂詞將兩個數字(A 和 B)相加,並將結果與 C 統一。以下程式稍微複雜一些。
fac(0,1).
fac(A,B) :-
A > 0,
Ax is A - 1,
fac(Ax,Bx),
B is A * Bx.
此程式計算 A 的階乘(數學表示法中的 A!)。
它遞迴地工作。第一條規則指出 0 的階乘是 1。第二條規則指出,大於 0 的數字 A 的階乘是 A-1 的階乘乘以 A。
(1) Prolog 對以下查詢(在空資料庫上)將給出什麼答案?嘗試自己思考答案,然後使用 Prolog 編譯器驗證它。
- ?- X = 1 + 2 + 3.
- ?- X is 100/10.
- ?- X is (14 + 16)/3, X + 3 = Y.
- ?- X = 1000/100 + 5, Y is X.
(2) 編寫一個名為 sigma 的謂詞,使得當 N=A+(A+1)+(A+2)+...+(B-2)+(B-1)+B 時,sigma(A,B,N) 為真。換句話說,. 您可以假設 A 和 B 是整數,且 B>A。使用以下查詢測試您的謂詞
?- sigma(4,9,X). X = 39 ; fail. ?- sigma(-7,-2,X). X = -27 ; fail. ?- sigma(-5,5,X). X = 0 ; fail.
(3) 本章末尾顯示的階乘程式違反了使用遞迴規則的指南之一。在第二條規則中
fac(A,B) :-
A > 0,
Ax is A - 1,
fac(Ax,Bx),
B is A * Bx.
遞迴部分不是規則中的最後一個謂詞。
- 展示 Prolog 如何評估查詢 ?- fac(3, X). 並解釋為什麼程式如此設定。
- 解釋為什麼行 A > 0 是必要的。如果缺少該行,Prolog 在找到答案後會做什麼?
(1) ?- X = 1 + 2 + 3.
X = 1 + 2 + 3.
?- X is 100/10.
X = 10.
?- X is (14 + 16)/3, X + 3 = Y.
X = 10.
Y = 10 + 3.
?- X = 1000/100 + 5, Y is X.
X = Y, Y = 15.
(2) 像往常一樣,解決這個問題的方法不止一種。以下是一種與階乘謂詞類似地使用遞迴的方法。
sigma(A,A,A). sigma(A,B,N) :- B>A, %What do you think would happen if you removed this line? Try it. Why does this happen? A1 is A+1, sigma(A1,B,N1), N is A+N1.
尾遞迴方式:sigma(A,B,N):- add_1(A,B, A, N).
add_1(B,B,N,N).
add_1(A,B,Count,N):-
B > A, A1 is A + 1, Count1 is Count + A1, add_1(A1, B, Count1, N).