Prolog的分部和剩余部分

时间:2013-11-13 12:51:11

标签: integer prolog division modulus

试图弄清楚如何写一个递归谓词divide_by(X,D,I,R),它将正整数X和除数D作为输入,并将答案作为整数I部分和其余部分返回R,然而,我似乎无法理解Prolog。我该怎么做呢?

3 个答案:

答案 0 :(得分:3)

有预定义的可评估仿函数。

(div)/2(mod)/2总是向下舍入。由LIA-1,Knuth等推荐。

(//)/2(rem)/2向零舍入(实际上,它是实现定义的,但所有当前实现都是这样做的)。您可以通过current_prolog_flag(integer_rounding_function, F)提出此问题,该问题在当前实施中提供toward_zero

这些对之间的差异仅在涉及负数时显示。这是一种偏爱的宗教战争。 ISO / IEC 10967:2012语言无关算术(vl.LIA-1)仅提供舍入“由于倾向于错误使用”(C.5.1.2.2)of towards_zero,而Fortran和追随者喜欢C转向towards_zero,称之为“algebraic”(6.5.5)。也可以看看: Advantages of using truncation towards minus infinity vs towards zero

答案 1 :(得分:0)

如果必须将算术运算限制为加法,减法,则可以按如下方式使用递归:

divit(Dividend, Divisor, Q, R) :-
    Dividend > 0,    % Only allow positive dividend
    Divisor \== 0,   % Don't allow 0 divisor
    % Use an accumulator (starts at 0) for the quotient, counting subtractions
    % of the divisor from the dividend 
    divit(Dividend, Divisor, 0, Q, R).

% If Dividend < Divisor, then
%    quotient accumulator is quotient and dividend is remainder, done!
divit(Dividend, Divisor, Qacc, Qacc, Dividend) :-
    Dividend < Divisor.

% If Dividend >= Divisor, then
%    subtract the divisor from the dividend
%    increment the quotient accumulator
%    recurs on updated dividend and quotient accumulator until dividend < divisor
divit(Dividend , Divisor, Qacc, Q, R) :-
    Dividend >= Divisor,
    D1 is Dividend - Divisor,
    Qacc1 is Qacc + 1,
    divit(D1, Divisor, Qacc1, Q, R).

答案 2 :(得分:0)

我假设你的老师正在尝试教授递归。

分割是重复减法,正如乘法重复加法, n'est-ce-pas

一个常见的prolog习惯用法,因为变量只能被赋值一次,就是有一个外部的“公共”谓词,它调用一个使用累加器并执行实际工作的私有“worker”谓词。这导致我们得到这样的解决方案。

%
% 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。这将使您获得数学正确的结果(可能与通过计算机的整数除法指令获得的结果不同)。应该注意的是,对于上面提到的财产是真实的,商的符号和余数的符号可能不同。