Разделение двух целых чисел альтернативным способом
Давайте рассмотрим, что n=s(s(...s(0)...)) (просто n= s^n(0)). Как можно написать программу, вычисляющую деление двух целых чисел? Я имею в виду s^(n//m) (это определение деления). Есть идеи? Например, если у нас возник вопрос:
?-divide(s(s(s(s(0)))),s(0),D).
я написал следующий код:
nat(0).
nat(s(X)) :- nat(X).
divide(0,_,D) :- D is 0.
divide(s(X),s(Y),D) :- divide(X,Y,D).
3 ответа
Ваш предикат divide/3
ошибочно предполагает, что следующее уравнение выполняется, когда x и y являются числами: (x-1) / (y-1) = x / y
Контрпример: (16-1) / (4-1) = 5 отличается от 16/4 = 4
Кажется, вы пытаетесь основать свой предикат на хорошо известном предикате сложения:
add(0,Y,Y).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
но деление является мультипликативной, а не аддитивной операцией. Возможный способ решения вашей проблемы - представить деление как повторное вычитание (так как умножение - это повторное сложение). Поскольку ваш предикат находится на натуральных числах, он должен реализовывать интегральное деление, как вы написали в вопросе.
s(0).
s(X):- X.
plus(0, Y, Y).
plus(s(X), Y, s(Z)):- plus(X , Y , Z).
minus(A, B, C) :- plus(C, B, A).
divide(_, 0, 0).
divide(0, _ , 0).
divide(X, s(0), X).
divide(A, B, s(N)) :- minus(A, B, R), divide(R, B, N).
Пример:
| ?- divide(s(s(s(0))), s(0), N).
N = s(s(s(0))) ?
yes
| ?- divide(s(s(s(s(0)))), s(s(0)), N).
N = s(s(0)) ?
yes
Это решение, очевидно, работает только для совершенных делений, таких как 4/2 или 6/3 и т. Д. Поскольку мы можем представлять только натуральные числа с использованием чисел Пеано.
Старый пост, но у меня такое же назначение. Так что ответ:
%nat:Is X natural?,nat2:Is X,Y naturals?
nat(0).
nat(s(X)) :- nat(X).
nat2(0,s(Y)) :- nat(Y).
nat2(s(X),s(Y)) :- nat2(X,Y).
%Summary of X+Y=Z
sum(X,0,X) :- nat(X).
sum(X,s(Y),s(Z)) :- sum(X,Y,Z).
%Minus of X-Y=Z is same as Y+Z=X
minus(X,Y,Z) :- sum(Y,Z,X).
%Multiplication of X*Y,add X+0(Z) Y times(recursive)
mult(X,0,0).
mult(X,s(Y),D):-mult(X,Y,Z), sum(X,Z,D).
%Divide,check special occasions,add to W the s(0)(1) recursive.
divide(X,Y,D) :- div(X,Y,D,_).
div(s(X),0,undefined,_).
div(0,s(Y),0,_).
div(0,0,undefined,_).
div(X,Y,0,X) :- X \== 0,Y \== 0,nat2(X,Y).
div(X,Y,D,L) :- X \== 0,Y \== 0,minus(X,Y,Z),div(Z,Y,W,L),sum(W,s(0),D).