Prolog将文本转换为数字并执行算术运算

Prolog将文本转换为数字并执行算术运算,prolog,Prolog,我第一次在prolog中工作。 我正在尝试转换文本中的操作。 比如,, 三加三等于六 应该返回true。 我试过这个。 我在最后一行遇到错误,当我尝试添加(一,一,二)时,它返回false而不是true numericValue(ONE, 1). numericValue(TWO, 2). numericValue(THREE, 3). numericValue(FOUR, 4). numericValue(FIVE, 5). numericValue(SIX, 6). numericValue

我第一次在prolog中工作。 我正在尝试转换文本中的操作。 比如,, 三加三等于六 应该返回true。 我试过这个。 我在最后一行遇到错误,当我尝试添加(一,一,二)时,它返回false而不是true

numericValue(ONE, 1).
numericValue(TWO, 2).
numericValue(THREE, 3).
numericValue(FOUR, 4).
numericValue(FIVE, 5).
numericValue(SIX, 6).
numericValue(SEVEN, 7).
numericValue(EIGHT, 8).
numericValue(ZERO, 0).
numericValue(NINE, 9).


add(num1,num2,num3):-
    numericValue(num1,a),
    numericValue(num2,b),
    numericValue(num3,c),
    (c =:= a+b -> true ; false).

istBiggerThen(XinEng,YinEng) :-
    numericValue(XinEng, X),
    numericValue(YinEng, Y),
    (  X < Y -> true ;  false).

A  + B = C :- add(A,B,C).
l
iterals(小写)与
V
ariabls(大写): 正如@潜伏者所指出的,你把你的原子和变量搞混了。所以你的事实应该是这样的:

text_to_number(one, 1).
text_to_number(two, 2).
text_to_number(three, 3).
%% etc...
虽然您的规则需要使用变量,例如:

add(A_Text, B_Text, C_Text) :-
    text_to_number(A_Text, A_Num),
    text_to_number(B_Text, B_Num),
    C_Num is A_Num + B_Num,
    text_to_number(C_Text, C_Num).

bigger_than(A_Text, B_Text) :-
    text_to_number(A_Text, A_Num),
    text_to_number(B_Text, B_Num),
    A_Num > B_Num.
add(ONE,ONE,TWO)
结果为false的原因是
add/3
的原始规则仅定义原子
num1、num2、num3、a、b、c之间的关系。查询
add(一,一,二)
Prolog尝试将变量与规则头部的原子统一起来,即
add(num1,num2,num3)
。因为查询的第一个和第二个参数是
ONE
,所以这种统一是不可能的,因为
ONE=ONE
但是
num1\=num2
。由于
add/3
没有进一步的规则或事实,因此查询只返回
false


使用模式(|条件|->真;假): 子句主体中的语句(即
:-
运算符右侧的语句)被计算为true或false,因此您几乎不需要使用模式
(| Condition |->true;false)
。例如,
C_Num是A_Num+B_Num
为真,如果
C_Num
可以与
A_Num
B_Num
之和统一,否则为假,在这种情况下,Prolog将开始回溯


使用
=:=/2
是/2
=:=/2
检查第一个参数与第二个参数的值是否相等,第二个参数可以是一个算术表达式,可以使用
is/2
进行计算。查询
?-X=:=2+2
,您将得到一个实例化错误,因为
=:=/2
无法将自由变量与数学表达式进行比较<另一方面,code>是/2
,它将左侧的变量与右侧表达式的值统一起来:
?-X是2+2。X=4

您使用
=:=/2
是可行的(前提是您理顺了变量atom),但您的规则描述了一个低效且迂回的解决方案,原因如下:因为
numericValue(Num3,C)
在计算算术之前,Prolog将首先统一
numericValue(Num3,C)
与第一个拟合事实,即<代码>数值值(一,1)然后测试
1=:=A+B
。当此操作失败时,Prolog将与下一个事实
数值值(2,2)
统一,然后测试
2=:=A+B
,然后下一个。。。直到它最终发生在正确的值上。与我建议的规则相比:数值
A_Num
B_Num
C_Num是A_Num+B_Num
相加,将
C_Num
与和统一。然后,Prolog将
text\u与\u编号(C\u text,C\u Num)
统一为具有
C\u Num
适当值的单个拟合事实


定义运算符: 当术语出现在正在定义的
:-
的右侧或程序的顶层时。但是,您不能简单地重新定义谓词(可以这样做,但需要一些簿记和特殊声明。参见,
dynamic/1
)。此外,您不想重新定义核心术语,如
+/2
=/2
。但是您可以相对轻松地定义自己的谓词。事实上,使用谓词定义发疯是我最喜欢的Prolog闲置工作之一(尽管我已经阅读了在实践中避免使用不必要的运算符的注意事项,因为它会使代码变得晦涩难懂)

在指令中使用
op/3
声明运算符。它具有签名
op(+优先级,+类型,:名称)
(参见):

在行动中:

?- one ++ two  =::= X.
X = three.

一个主要问题是,在Prolog中,变量以大写字母开头,原子(常量)以小写字母开头。你似乎在好几个地方把这个颠倒过来了。另外,
=/2
是内置的统一运算符(它不是表达式的算术等式)。当您输入
A+B=C:-add(A,B,C)
时,尝试重新定义
=/2
的含义,这是不允许的。尝试添加(A_文本,B_文本,C_文本):-numericValue(A_文本,A_Num),numericValue(B_文本,B_Num),C_Num是A_Num+B_Num,Num(C_文本,C_Num)。仍然为add(一,一,一)提供true。@rbh假设代码中的其他所有内容都正确,我假设变量
ONE
与原子
zero
相统一,为您提供
add(零,零,零)。
您的序言顶层是否没有显示给出真实结果的
ONE
的值?如果我错了,请告诉我。我很乐意看一看您当前的代码。@rbh,如果您试图测试错误的声明“一+一=一”是否为真,您需要
添加(一,一,一)
@rbh您是否了解关于以大写字母开头的名称与以小写字母开头的名称的说法
add(一,一,一)
就像
add(X,X,X)
<代码>一是一个变量
X
是一个变量。那是因为它们都以大写字母开头。查询
add(ONE,ONE,ONE)
询问当添加到自身时会产生什么值(使用变量
ONE
)。答案将是
ONE=zero
。另外关于定义运算符,如果我按照您指定的方式定义,它是否也适用于“ONE++two++two=:=six”?
:- op(200, xfx, user:(++)).
:- op(300, yfx, user:(=::=)).

A ++ B =::= C :- add(A, B, C).
?- one ++ two  =::= X.
X = three.