【问题标题】:Inverse Factorial Function (Prolog)反阶乘函数 (Prolog)
【发布时间】:2013-11-12 21:50:46
【问题描述】:

我必须编写一个 Prolog 程序来计算阶乘函数的逆而不使用除法。我还得到了注释:“函数的逆不一定是函数”。我把它作为一个正常的阶乘谓词..

fact(0,1).
fact(N,F) :- N>0, N1 is N-1, fact(N1,F1), F is N * F1.

我在其他一些帖子上读到过,您应该可以只切换参数,但这个版本似乎并非如此。谁能帮我找出原因?

【问题讨论】:

  • 因为N>0 要求N 是基础算术值。 N1 is N-1 bit 也是如此。
  • 这句话的意思是调用invfact(X,1) 应该成功两次。对吗?
  • 我相信是的。所以我必须改变函数的主体?
  • 我会使用你的 fact 更改为生成谓词 - 这样会生成一个给定值的阶乘列表 - 因为对更好,(N, F) 其中 F 是 N! - 然后从末尾搜索该列表以查找我的索引。
  • 我对 Prolog 很陌生。是否可以为我指明如何完成此任务的正确方向?

标签: prolog factorial


【解决方案1】:

请参阅Inverse factorial in Prolog 以获得干净的关系解决方案,但如果我们这样做了:

inv_fact(RF, N) :-
   (  between(0,RF,N),
      fact(N,F),
      F >= RF
   -> F = RF
   ;  false
   ).
inv_fact(1, 1).

【讨论】:

    【解决方案2】:

    这个怎么样?我们只是在使用您的谓词 fact/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).
    

    【讨论】:

    • 感谢 false 帮助我改进答案。
    【解决方案3】:

    我认为您需要更改逻辑,颠倒评估“流程”。 N 是未知数,但 fact/2 假设是有界的。

    如果你使 fact/2 尾递归,添加一个累加器,你将更有利于解决这个问题,因为你还可以添加已知的阶乘(比如 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 
    

    edit 当然,sn-p 不仅是作弊,而且效率极低。

    一个高效的,实现我上面给出的提示

    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
        ).
    

    【讨论】:

      猜你喜欢
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2021-01-17
      • 1970-01-01
      相关资源
      最近更新 更多