Integer Prolog中的除法与余数
试图弄清楚如何编写一个递归谓词除以(X,D,I,R),它以一个正整数X和一个除数D作为输入,并以整数I部分和余数R部分返回答案,然而,我似乎无法理解Prolog。我该怎么做呢?如果必须将算术运算限制为加法、减法,那么可以使用递归,如下所示:Integer Prolog中的除法与余数,integer,prolog,division,modulus,Integer,Prolog,Division,Modulus,试图弄清楚如何编写一个递归谓词除以(X,D,I,R),它以一个正整数X和一个除数D作为输入,并以整数I部分和余数R部分返回答案,然而,我似乎无法理解Prolog。我该怎么做呢?如果必须将算术运算限制为加法、减法,那么可以使用递归,如下所示: divit(Dividend, Divisor, Q, R) :- Dividend > 0, % Only allow positive dividend Divisor \== 0, % Don't allow 0 div
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).
divit(被除数、除数、Q、R):-
股息>0%,仅允许正股息
除数\==0,%n不允许0除数
%使用累加器(从0开始)计算商,计算减法
%除数的除数
除数(被除数,除数,0,Q,R)。
%如果除数<除数,则
%商累加器是商,红利是余数,完成!
除数(股息、除数、Qacc、Qacc、股息):-
除数。
%如果股息>=除数,则
%从股息中减去除数
%增加商累加器
%在更新的除数和商累加器上递归,直到除数<除数
除数(被除数、除数、Qacc、Q、R):-
股息>=除数,
D1是除数因子,
Qacc1是Qacc+1,
除数(D1,除数,Qacc1,Q,R)。
此函数有预定义的可计算函子
(div)/2和(mod)/2始终向下舍入。由LIA-1、Knuth等推荐
(//)/2
和(rem)/2
向零舍入(实际上,它是实现定义的,但所有当前的实现都是这样做的)。您可以通过current\u prolog\u标志(integer\u rounding\u function,F)
来询问这一点,该标志在当前实现中给出了向零的方向
只有当涉及负数时,这些对之间的差异才会显示出来。这是一场人们更喜欢的宗教战争。ISO/IEC 10967:2012语言无关算术(vl.LIA-1)只提供了“由于错误使用的倾向”(C.5.1.2.2)向零舍入,而Fortran和类似C的追随者则向零舍入,称之为“代数”(6.5.5)。另见:
我想你的老师是在教递归
除法是重复的减法,就像乘法是重复的加法,不是吗
由于变量只能被赋值一次,一个常见的prolog习惯用法是有一个外部的“public”谓词,它调用一个私有的“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
相当于M-N
。这将使您得到数学上正确的结果(可能与通过计算机的整数除法指令获得的结果不同)。需要注意的是,如果上述属性为真,商的符号和余数的符号可能不同。您是否阅读过教程?为什么需要递归谓词而不是整数算术呢?正如我说的,mate是prolog的新手,找不到任何教程来说明我需要做什么。我不确定我是否理解你的意思。好吧,伙计,如果你花时间阅读,有足够多的教程可以告诉你需要做什么。我的意思是,I is X div D
会给你整个部分,R is X rem D
会给你剩下的部分()。我不知道你为什么要写递归谓词。所以你应该像这样输入代码:除以(X,d,I,R):-I是X div d,R是X rem d,然后像这样问-?-除以(12,5,I,R)。例如?你可以,但那里没有递归:)我假设他实际上有类似于0,s(0),…
的东西,而不是整数,但他拒绝说,所以我们只能猜测。@Boris-我没有得到任何东西来输入它,它只会是整数
M = N * Q + R