你的問題是,你不能實例化已經實例化了一個不同的術語的變量。 因此,如果計數已經實例化(比如用2),則不能計數爲計數-1。
is/2運算符需要左變量沒有實例化(或用實際的表達式值實例化),並且正確的表達要充分評估。 這同樣適用於遞歸調用。一旦Res被實例化爲一個整數,您就不能將其值更改爲另一個整數。
這裏去另一個實現:
rand_val(Count, Rng, Res):-
rand_val(Count, Rng, -1, Res).
rand_val(0, _, Value, Value):-
!,
Value >= 0.
rand_val(Count, Rng, MValue, Value) :-
succ(NCount, Count),
X is random(Rng), %rand_int(Rng, X),
NValue is max(X, MValue),
rand_val(NCount, Rng, NValue, Value).
首先注意到我寫了兩個謂詞rand_val/3和rand_val/4。 前者是你想要的簽名。 後者有一個更多的參數,它將保持當時發現的最大值。
第一個謂詞只是調用rand_val/4賦值-1作爲找到的最大值。
現在rand_val/4的第一個子句檢查其輸入參數「Count」是否爲0.在這種情況下,它禁止回溯(使用剪切)並檢查Value是否爲有效值。如果它是< 0,那是因爲你用Count = 0調用了rand_val/3,所以它確實從未發出隨機數。
如果它> 0,它只是統一了第三個和第四個參數(注意第四個參數是你期待的輸出值)。
現在到第二個子句: 首先它做一個succ(NCount,Count),其中NCount是一個新變量。它將通過Count(Count-1)的前身進行實例化。
然後我們計算一個隨機數。我正在使用SWI prolog,因此我隨機調用(Max)來獲得隨機數。這用它來實例化新變量X.
在這一點上,我們有中間結果(MValue)和X
最後我們做遞歸步驟,現在稱rand_val/4與新的計算值NCOUNT和n值之間選擇的最大值。
請注意,當我們從遞歸返回(它在rand_val/4的第一個子句中被綁定)時,變量Value被實例化。
我將它複製到tuProlog的IDE,並且在運行rand_val(0,100,Res)時仍然得到「no」。我認爲最大/ 2不起作用。我可以創建一個max/3,但無法弄清楚如何做一個「返回值」的最大值(如果這是Prolog中的正確術語)。 – Makis 2011-03-16 07:45:42
@Makis:也許TuProlog沒有實現最大的算術函數。在這種情況下,你可以寫下你自己的max/3謂詞:max(A,B,Max): - A> B - > Max = A; MAX = B中。然後,您將使用'max(X,MValue,NValue)'替換'NValue is max(X,MValue)' – gusbro 2011-03-16 13:04:23
謝謝您的出色答案! – Makis 2011-03-17 06:35:54