我在Prolog中编写了一个处理单位转换的程序,但我总是遇到堆栈溢出:你知道为什么吗?

问题描述 投票:0回答:1

无论重构如何,问题仍然存在,但情况发生了变化,如果我切换第 6 行和第 7 行,我会得到不同的结果吗?这怎么可能?

如果相关的话,这是 MacOS Monterey(版本 12.6.2)设备上的 gnuprolog。

相关代码如下:

conversion(meters, 82/25, feet).
conversion(feet,   12/1,  in  ).
conversion(hr,     60/1,  min ).
conversion(min,    60/1,  sec ).

conversion(Unit1, X/Y, Unit2)     :- conversion(Unit2, Y/X, Unit1), !.
conversion(Unit1, Num/Den, Unit3) :- conversion(Unit1, X/Y, Unit2), conversion(Unit2, A/B, Unit3), Num is X * A, Den is Y*B.

每当我输入一个需要多个inversion的问题(如倒数第二条规则)时,我都会收到错误。所以,

conversion(meters,X,in).  
conversion(hr,X,sec).
conversion(in, X, meters).

原因,

Fatal Error: local stack overflow (size: 16384 Kb, reached: 16384 Kb, environment variable used: LOCALSZ)

但是

conversion(min,X,hr).
conversion(feet,X,meters).

产生预期的结果。任何智慧将不胜感激!

prolog stack-overflow gnu-prolog
1个回答
0
投票

以下内容似乎有效,谢谢@brebs!

conversion(meters, 82/25,feet   ).
conversion(feet,   12/1, inches ).
conversion(hours,  60/1, minutes).
conversion(minutes,60/1, seconds).

walk(Unit1, X/Y, Unit3, Vs) :-
     conversion(Unit1, X/Y, Unit3);
     conversion(Unit3, Y/X, Unit1);
     \+ member(Unit2, Vs),
     walk(Unit1, A/B,  Unit2, [Unit2|Vs]),
     walk(Unit2, C/D , Unit3, [Unit2|Vs]),
     N is A * C, M is B * D,
     gcd(N,M,Z),
     X is N // Z,
     Y is M // Z.

ratio(Unit1, X/Y, Unit2) :- walk(Unit1, X/Y, Unit2, []).

gcd(X, 0, X):- !.
gcd(0, X, X):- !.
gcd(X, Y, D):- X =< Y, !, Z is Y - X, gcd(X, Z, D).
gcd(X, Y, D):- gcd(Y, X, D).
© www.soinside.com 2019 - 2024. All rights reserved.