3

私は SWI-Prolog が初めてで、Prolog で素数関数を確認したいと考えています。

prime(N) :-
    N > 1,
    M is N - 1,
    check(N, M).

check(_, 1).
check(N, M) :-
    M > 1,
    R is N - M * N / M,
    R > 0,
    P is M - 1,
    check(N, P).

しかし、Prolog で, ,... の2 + 2ような別の演算子を尋ねると、次のように表示されます。または用だと思います。再割り当てしますが、このエラーが再び発生します。なぜ?(*)/2(/)/2undefined procedure: (+)/2seetellsee(user)tell(user)

4

3 に答える 3

6

SWI プロローグ 6.0.2 では、使用した除算は浮動小数点数を返します。たとえばprime(13)、剰余が 0 であるため、失敗します。整数除算は operator を使用します//。ただし、プロローグの SWI 関数remmod.

また、 の最初の定義の後にカットが必要ですcheck。そうしないと、プロローグは 2 番目の定義を調査し、false を返します。Cut は、N より小さい自然数をすべてチェックした後、成功して停止することを保証します。

これは、SWI Prolog 6.0.2 で必要に応じて動作する修正されたコードです。

prime(N) :-
    N > 1,
    M is N - 1,
    check(N, M).

check(_, 1) :- !.
check(N, M) :-
    M > 1,
    R is N mod M,
    R > 0,
    P is M - 1,
    check(N, P).
于 2012-06-11T10:23:18.580 に答える
4

あなたのエラーについては、これをチェックしてください:

?- 2+2.
ERROR: Undefined procedure: (+)/2

?- X is 2+2.    
X = 4 

is算術式の評価を強制するために Prolog で使用することになっています。help(is).SWI-Prolog のプロンプトで" " と入力してみてください。

しかし、2 つの理由から、あなたのアルゴリズムは非常に非効率的です。最初に、前のすべての数で割り切れるか候補数をチェックしますが、その平方根より大きくない数だけで十分です (ifa*b=nおよびa >= sqrt(n)then b =< sqrt(n))。

次に、逆の順序でテストします。小さな因子の倍数は、大きな因子の倍数よりもはるかに頻繁に発生するため、昇順で実行するとテストがはるかに早く終了し、プログラム全体の実行がはるか高速になります。最後に、2 以外の偶数でテストする必要はありません。

prime(2).
prime(N) :- N > 1,
    N mod 2 > 0,              % is odd
    M is floor(sqrt(N+1)),    % round-off paranoia 
    check(N, M, 3).

check(N, M, F) :- F>M.
check(N, M, F) :- F=<M,
    N mod F > 0,
    F1 is F + 2,              % test by odds only
    check(N, M, F1).

primesFromTo(F,T,X):-
  between(F,T,X), prime(X).
于 2012-06-13T06:45:18.530 に答える
2

あなたが言及しているseeand tell: これらは非常に昔ながらの組み込み述語です。それらを避けるほうがよい。[file]ファイルのロードと再ロードに使用しますmake

テスト素数のより良い実装については、この回答を参照してください。

于 2012-07-09T16:48:45.520 に答える