Search code examples
prologgreatest-common-divisor

Highest integers common factor testing error


I would like the following bar/3 predicate to print false if the integers A and B do not have C as highest common factor else it should print true,but as of now it's giving an error in case C is not HCF. I am not sure how to fix this.

foo(P,Q,R):-L is P/Q,R is P-Q*floor(L).
bar(A,0,A).
bar(A,B,C):-foo(A,B,X),bar(B,X,C).

for example,in case of error,I am getting

?- bar(27,30,1).
ERROR: //2: Arithmetic: evaluation error: `zero_divisor'

instead of

?- bar(27,30,1).
false

and on success I get the correct result I want

?- bar(27,30,3).
true

Solution

  • First there is a cut missing. You want that the first clause of bar/3 is executed for =0, and the second clause of bar/3 is executed for <>0. This can be done with a cut:

    foo(P,Q,R):-L is P/Q,R is P-Q*floor(L).
    bar(A,0,A) :- !.
    bar(A,B,C):-foo(A,B,X),bar(B,X,C).
    

    But the cut doesn't work correctly, if the third argument is bound. Since the first clause might then fail because the unification of the first argument and third argument fails, and not because <>0.

    So you need a second rewrite to make the predicate steadfast in the last argument:

    foo(P,Q,R):-L is P/Q,R is P-Q*floor(L).
    bar(A,0,B) :- !, B=A.
    bar(A,B,C):-foo(A,B,X),bar(B,X,C).
    

    Now everything works fine, as the following example run shows:

     Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.1.22)
     Copyright (c) 1990-2014 University of Amsterdam, VU Amsterdam
     ?- bar(27,30,1).
     false.
    
     ?- bar(27,30,3).
     true.
    

    Bye

    BTW: You can extend the working range of the predicate tremendously, by not using floats, but the ordinary integers, which are for most modern Prolog systems without a fixed bound.

    The code then reads as follows, using a more appropriate predicate name:

    gcd(X, 0, Y) :- !, Y = X.
    gcd(X, Y, Z) :-
       H is X rem Y,
       gcd(Y, H, Z).