ただし、正の整数 X と除数 D を入力として受け取り、整数部分 I と剰余部分 R として答えを返す再帰述語divide_by(X、D、I、R) を作成する方法を理解しようとしていますが、 、私はプロローグを理解できないようです。どうすればこれを行うことができますか?
3 に答える
これには、事前定義された評価可能なファンクターがあります。
(div)/2
(mod)/2
常に切り捨てます。LIA-1、Knuthなどで推奨。
(//)/2
ゼロに向かって(rem)/2
丸めます(実際には、実装で定義されていますが、現在の実装はすべてそのようにしています)。current_prolog_flag(integer_rounding_function, F)
which Gives in current implementation を介してこれを尋ねることができますtoward_zero
。
これらのペアの違いは、負の数が含まれている場合にのみ表示されます。どちらを好むかは一種の宗教戦争です。ISO/IEC 10967:2012 言語に依存しない算術演算 (vl. LIA-1) は、toward_zero の「誤用の傾向があるため」 (C.5.1.2.2) の丸めのみを提供しますが、Fortran や C などのフォロワーは、それを呼び出して toto_zero を使用します。代数」(6.5.5)。参照: マイナス無限大とゼロに向かって切り捨てを使用する利点
あなたの先生は再帰を教えようとしていると思います。
掛け算が足し算の繰り返しであるように、割り算は引き算の繰り返しです。n'est-ce-pas ?
変数には一度しか値を割り当てることができないため、一般的なプロローグのイディオムは、アキュムレータを使用して実際の作業を行うプライベートな「ワーカー」述語を呼び出す外側の「パブリック」述語を持つことです。これは、このような解決策につながります。
%
% divide M (the dividend) by N (the divisor),
%yielding the quotient (Q) and remainder (R).
integer_division( M , N , Q , R ) :-
M > 0 ,
N > 0 ,
div_rem( M , N , 0 , Q , R )
.
%
% internal worker predicate for integer division
% requires dividend and divisor both to be unsigned (positive).
%
div_rem( M , N , Q , Q , M ) :- % dividend M < divisor N? We're done.
M < N , % - unify the accumulator with the quotient
. % - and unify the divisor with the remainder
div_rem( M , N ,T , Q , R ) :- % dividend M >= divisor N?
M >= N , % - increment the accumulator T
T is T+1 , % - decrement the divisor by N
M1 is M-N , % - recurse down
div_rem( M1 , N , T1 , Q , R ) % - That's all.
. % Easy!
これから、署名されたオペランドを説明するために外側のパブリック述語を変更するのは非常に簡単です。
+/+
収量+
+/-
収量-
-/+
収量-
-/-
収量+
そして、それを評価M/N
して商Q
と剰余を求めるとR
、その性質は
M = N * Q + R
が当てはまります。これにより、商と剰余に必要な符号がわかるはずです。M + -N
負の数の足し算は引き算と同じであることを忘れないでくださいM - N
。これにより、数学的に正しい結果が得られます (コンピューターの整数除算命令によって得られる結果とは異なる場合があります)。上記の特性が真であるためには、商の符号と剰余の符号が異なる場合があることに注意してください。