我必须在不使用除法的情况下将Prolog程序写入计算机中的阶乘函数的逆。我还得到了一个说明:“函数的逆函数不一定是函数”。我将此作为正常的因子谓词。
fact(0,1).
fact(N,F) :- N>0, N1 is N-1, fact(N1,F1), F is N * F1.
我已经读过其他一些帖子,你应该只能切换参数,但这个版本似乎并非如此。任何人都可以帮我解决原因吗?
答案 0 :(得分:2)
请参阅Inverse factorial in Prolog了解干净的关系解决方案,但如果我们参与其中:
inv_fact(RF, N) :-
( between(0,RF,N),
fact(N,F),
F >= RF
-> F = RF
; false
).
inv_fact(1, 1).
答案 1 :(得分:1)
这个怎么样?我们只使用你的谓词事实/ 2生成因子,如果我们得到一个匹配因子的点,我们就会停止,否则我们会生成下一个。
fact(0,1).
fact(N,F) :- N>0, N1 is N-1, fact(N1,F1), F is N * F1.
inv_fact(1,0).
inv_fact(Value,Number) :- inv_fact(Value,1,Number).
inv_fact(Value,Num,Num) :- fact(Num,Value).
inv_fact(Value,Num,Number) :- fact(Num,V), Value < V,!,false.
inv_fact(Value,Num,Number) :- fact(Num,V),
not(Value=V),
NumNew is Num+1,
inv_fact(Value,NumNew,Number).
答案 2 :(得分:0)
我认为你需要改变逻辑,扭转评估'流程'。 N是未知数,但事实/ 2假定是绑定的。
如果你使fact / 2 tail递归,添加一个累加器,你将能够更好地解决这个问题,因为你也可以添加已知的factorial(比如K)和未知的(比如U),然后测试:
if F1 equals K (we have found the solution), unify U to N
if F1 > K, there is no solution... let Prolog fail...
否则,有点作弊......
?- between(1,inf,X), fact(X,F), F >= 120.
X = 5,
F = 120
编辑当然,该片段不仅是骗子,而且非常低效。
一个有效的,实现我上面给出的提示
factinv(1, 0). % conventional
factinv(K, U) :- factinv(1, K, 1, U).
factinv(C, K, N, U) :-
F is C * N,
( F < K
-> M is N+1,
factinv(F, K, M, U)
; F == K
-> N = U
).