【问题标题】:program for finding Gcd in Prolog在 Prolog 中查找 Gcd 的程序
【发布时间】:2014-03-17 09:22:49
【问题描述】:

我尝试在 Prolog 中编写代码来查找 GCD(不使用模数) 谁能告诉我这个程序有什么问题?

gcd(X,Y,Z):- X>=Y, X1=X-Y, gcd(X1,Y,Z).
gcd(X,Y,Z):- X<Y, X1=Y- X, gcd(X1,X,Z).
gcd(0,X,X):- X>0.

【问题讨论】:

    标签: prolog greatest-common-divisor


    【解决方案1】:

    至于为什么原来的实现不行,有两个原因:

    谓词=/2 是为了统一,而不是算术赋值

    表达式X1 = X - Y 不会从X 中减去Y 并将结果存储在X1 中。相反,它将X1 与术语-(X,Y) 统一起来。例如,如果X=5Y=3,那么结果将是X1=5-3,而不是X1=2。解决方案是使用 is/2 分配计算的算术表达式:X1 is X - Y

    除基本情况谓词外,其他谓词成功匹配基本情况

    子句gcd(0,X,X) :- X &gt; 0. 是一个合理的基本情况,但从未尝试过,因为第二个子句 (gcd(X,Y,Z):- X&lt;Y,...) 总是首先成功匹配相同的条件,导致无限递归和堆栈溢出。

    解决此问题的一种方法是将基本情况移动到第一个子句,并在成功执行后使用剪切以避免回溯:

    gcd(0, X, X):- X > 0, !.
    gcd(X, Y, Z):- X >= Y, X1 is X-Y, gcd(X1,Y,Z).
    gcd(X, Y, Z):- X < Y, X1 is Y-X, gcd(X1,X,Z).
    

    现在可以使用了:

    | ?- gcd(10,6,X).
    
    X = 2 ? ;
    
    (1 ms) no
    | ?- gcd(10,5,X).
    
    X = 5 ? ;
    
    no
    

    (注意:这里的“否”表示找到第一个解决方案后没有找到更多解决方案)


    附录

    在上述实现中仍然存在一些“差距”。一是它不能优雅地处理gcd(0, 0, R)(它会溢出)。其次,它不处理负值。一种可能的解决方案是详细说明这些情况:

    gcd(X, Y, Z) :-
        X < 0, !,
        gcd(-X, Y, Z).
    gcd(X, Y, Z) :-
        Y < 0, !,
        gcd(X, -Y, Z).
    gcd(X, 0, X) :- X > 0.
    gcd(0, Y, Y) :- Y > 0.
    gcd(X, Y, Z) :-
        X > Y, Y > 0,
        X1 is X - Y,
        gcd(Y, X1, Z).
    gcd(X, Y, Z) :-
        X =< Y, X > 0,
        Y1 is Y - X,
        gcd(X, Y1, Z).
    

    【讨论】:

    • 很好的解释! :-)
    【解决方案2】:

    请尝试以下方法:

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

    取自 GCD 上的rosettacode.org 各种语言。

    【讨论】:

    • 是正确的..你知道为什么我的原始程序是错误的吗?(除了“is”操作)。
    【解决方案3】:

    GCD 的 Prolog 代码

    gcd(X,Y,G) :- X=Y, G=X.
    gcd(X,Y,G) :- X<Y, Y1 is Y-X, gcd(X,Y1,G).
    gcd(X,Y,G) :- X>Y ,gcd(Y,X,G).
    
    ?- gcd(24,16,G).
    G = 8 
    

    【讨论】:

      【解决方案4】:
      gc(X,Y,Z):- (
          X=0 -> (
              Z is Y
          );
          Y=0 -> (
              Z is X
          );
          X=Y -> (
              Z is X
          );
          X>Y -> (
              Y1 is X-Y,
              gc(Y1,Y,Z)
          );
          X<Y->(
              Y1 is Y-X,
              gc(X,Y1,Z)
          )
      ).
      

      【讨论】:

      • 感谢您提供答案。您能否编辑您的答案以包括对您的代码的解释?这将有助于未来的读者更好地了解正在发生的事情,尤其是那些刚接触该语言并难以理解概念的社区成员。
      【解决方案5】:
      gcd(A,B,X):- B=0,X=A.
      
      gcd(A,B,X):- A>B, gcd(B, A, X).
      
      gcd(A,B,X) :- A<B, T is B mod A, gcd(A, T, X).
      

      【讨论】:

        【解决方案6】:

        prolog 答案是:-

        gcd(X,0,X).
        gcd(X,Y,R):-
        Y>0,
        X1 is X mod Y,
        gcd(Y,X1,R).
        

        【讨论】:

          【解决方案7】:

          使用欧几里得算法的两个数的 GCD 的简单易读 Prolog 代码。

          gcd(A,B,X):- A=0,X=B. % base case
          gcd(A,B,X):- B=0,X=A. % base case
          gcd(A,B,X):- A>B, gcd(B, A, X).
          gcd(A,B,X):- A<B, T is B mod A, gcd(A, T, X).
          

          查询如下:

          gcd(147,210,GCD).
          

          输出:

          GCD = 21
          

          【讨论】:

            【解决方案8】:

            此代码有效。

            gcd(X,X,X).

            gcd(X,Y,D):-X

            gcd(X,Y,D):-Y

            【讨论】:

            • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2016-03-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多