2017-02-19 82 views
2

我一直在學習序言中的遞歸,它似乎工作,但輸出是在一個非常奇怪的格式;序言返回H = 0 + 1 + 1而不是H = 2

mins_to_hours(In, H, M):- 
    In < 60, 
    H is 0, 
    M is In. 
mins_to_hours(In, H, M):- 
    In > 59, 
    H = H1 + 1, 
    In1 = In - 60, 
    mins_to_hours(In1, H1, M). 

是我的代碼,並給出查詢mins_to_hours(135, H, M). 的響應是

H = 0+1+1, 
M = 15 

我只是困惑,爲什麼分鐘的作品,但時間不會。 該程序應該將分鐘轉換爲小時和分鐘。 在此先感謝!

回答

2

在推理整數時,使用例如謂詞(#=)/2來表示等於的算術表達式。

例如,使用GNU序言:

 
mins_to_hours(In, H, M):- 
    In #< 60, 
    H #= 0, 
    M #= In. 
mins_to_hours(In, H, M):- 
    In #> 59, 
    H #= H1 + 1, 
    In1 #= In - 60, 
    mins_to_hours(In1, H1, M). 

因此,我只是用(#=)/2表達平等(#<)/2表達 「小於 」,並(#>)/2表達 「大於」。

實例查詢和回答:

 
| ?- mins_to_hours(135, H, M). 

H = 2 
M = 15 ? ; 

no 

它也可以在其他方向,比如:

 
| ?- mins_to_hours(Mins, 2, 15). 

Mins = 135 ? ; 

no 

最一般的查詢工程太:

 
| ?- mins_to_hours(Mins, H, M). 

H = 0 
M = _#2(0..59) 
Mins = _#2(0..59) ? ; 

H = 1 
M = _#72(0..59) 
Mins = _#2(60..119) ? ; 

H = 2 
M = _#136(0..59) 
Mins = _#2(120..179) ? 

在其他Prolog系統,您可能必須將庫導入我們e整數關係。例如,在SICStus Prolog,YAP和SWI中,使用library(clpfd)

相比之下,(=)/2您目前正在使用表示句法 統一,並且不評估算術表達式的謂語。

1

@mat對推理整數有正確的答案。

你看到H = 0+1+1的原因是因爲在Prolog +只是另一個函子。也就是說,H1 + 1相當於'+'(H1, 1),並且=/2運算符是而不是如同其他語言中的賦值。它確實統一條款。所以說,H = H1 + 1只需統一H與術語'+'(H1, 1)H1 + 1。如果H10統一,則H將與術語0 + 1統一。如果稍後H10 + 1統一併且您執行H = H1 + 1,則H將具有值0 + 1 + 1,依此類推。

如果要執行算術表達式,可以使用is/2。這是Prolog的文檔中描述:

H is H1 + 1 

這實際上評估H1 + 1假設它是一個有效的算術表達式(它是在這種情況下),所有的變量與數值實例化。 Prolog中還有其他運算符會執行算術表達式評估:</2,>/2,=:=/2等,以及CLP(FD)運算符,#=/2等,如@mat的答案中所述。這些在Prolog文檔中有描述。

相反,您正在使用is/2您應該使用統一。這:

mins_to_hours(In, H, M):- 
    In < 60, 
    H is 0,   % 0 is a trivial expression and doesn't need evaluating 
    M is In.   % In is a trivial expression and doesn't need evaluating 

應該寫成:

mins_to_hours(In, H, M):- 
    In < 60, 
    H = 0, 
    M = In. 

或者更簡潔的:

min_to_hours(In, 0, In) :- In < 60. 
相關問題