试图弄清楚如何写一个递归谓词divide_by(X,D,I,R),它将正整数X和除数D作为输入,并将答案作为整数I部分和其余部分返回R,然而,我似乎无法理解Prolog。我该怎么做呢?
答案 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
。这将使您获得数学正确的结果(可能与通过计算机的整数除法指令获得的结果不同)。应该注意的是,对于上面提到的财产是真实的,商的符号和余数的符号可能不同。