Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第三节,整数的比较

内容提要

Prolog中如何进行整数的比较

整数比较的实际应用

Prolog中如何进行整数的比较

一些Prolog的运算谓词可以实际地进行运算(即,不需要通过“is”协助),这些运算谓词都是进行整数比较的操作符。

运算实例      Prolog表达式

x < y         X < Y.

x ≤ y         X =< Y.

x = y         X =:= Y.

x /= y        X =\= Y.

x ≥ y          X >= Y.

x > y        X > Y.

这些操作符有明确的含义,可以直接在Prolog中使用:

?- 2 < 4.

true

?- 2 =< 4.

true

?- 4 =< 4.

true

?- 4 =:= 4.

true

?- 4 =\= 5.

true

?-  4 >= 4.

true

?- 4 > 2.

true

而且,这些操作符可以促使其左右两端的参数进行计算:

?- 2 < 4 + 1.

true

?- 2 + 1 < 4.

true

?- 2 + 1 < 3 + 2.

true

需要注意,=:=和=是不同的操作符,比如:

?- 4 = 4.

true

?- 2+2 = 4.

false

?- 2+2 =:= 4.

true

即,=会尝试对参数进行合一,而不是进行运算,=:=就会进行运算然后比较。

而且在使用这些操作符时,必须注意变量是已经被初始化的,比如,下面的所有例子都因为变量没有初始化而失败:

?- X < 3.

false

?- 3 < Y.

false

?- X =:= X.

false

而且,变量必须要被初始化为整数,比如:

?- X = 3, X < 4.

true

?- X = b, X > 4.

false

实际应用

下面我们通过一个实际的例子来学习如何将Prolog的比较数字能力运用到程序中。我们将会定义一个谓词,其第一个参数是由非负整数组成的列表,最后一个参数是返回的列表中的

最大值。同样,我们将会使用累加器。当遍历列表的过程中,累加器会保持当前找到的最大值,如果找到了更大的值,累加器会更新为新的最大值。当我们调用程序时,会将累加器的

初始值设置为0。下面是代码,请注意存在两个递归子句:

accMax([H|T], A, Max) :- H > A, accMax(T, H, Max).

accMax([H|T], A, Max) :- H =< A, accMax(T, A, Max).

accMax([], A, A).

第一个子句测试如果列表的头元素大于当前找到的最大值的情况,如果是,就会设置累加器为新的最大值,然后对列表的尾部进行递归操作。第二个子句测试列表的头元素等于小于当

前找到最大值的情况,如果是,就会继续使用当前累加器对列表尾部进行递归操作。最终,基础子句将第二个参数和第三个参数合一,将遍历列表后找到的最大值传递给第三个参数作为

结果。下面是查询的例子:

?- accMax([1, 0, 5, 4], 0, Max).

首先accMax的第一个子句会起作用,得到如下的新目标:

?- accMax([0, 5, 4], 1, Max).

注意累加器的值已经更新为1。然后,accMax的第二个子句会起作用,因为0(列表当前的头元素)比1小。这个过程会重复直到列表为空:

?- accMax([5, 4], 1, Max).

?- accMax([4], 5, Max).

?- accMax([], 5, Max).

最后,第三个子句会起作用,将变量Max和累加器合一:

Max = 5.

true

同样的,我们可以再定义一个谓词调用之前的谓词,并给出累加器;初始化的值。但是等等,我们应该将累加器的初始值赋值为什么?如果说是0,那么意味着我们假设列表中所有的数字

都是正数。但是如果有负数的列表,比如:

?- accMax([-11. -2, -7, -4, -12], 0, Max).

Max = 0

true

这个结果就不是我们期望的,因为列表中最大值应该是:-2。我们使用0作为累加器的初始值,但是它比列表中所有的数字都大。

有一个简单的方式解决这个问题:由于输入的列表是要求非空的整数组成的,所以将累加器的初始值设置为列表头元素的值。通过这种方式我们可以确保累加器初始值为列表中的数字之一,

如下是具体的实现:

?- max(List, Max) :- List = [H|_], accMax(List, H, Max).

所以,如果我们查询:

?- max([1, 2, 46, 53, 0], X).

X = 53.

true

如果我们查询:

?- max([-11, -2, -7, -4, -12], X).

X = -2.

true

能够得到期望的结果。

时间: 2024-07-30 11:53:33

Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第三节,整数的比较的相关文章

Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第一节,Prolog中的数字运算

内容提要 Prolog中的数字运算 Porlog运算的本质 Prolog中的数字运算 Prolog语言本身提供了一些基础的运算符号,对整数进行一些操作(即类似...-3, -2, -1, 0, 1, 2, 3等).多数Prolog的实现同时也提供了一些工具对实数进行操作 (比如浮点数,1.53,6.35,等等).但是我们不会讨论浮点数,因为浮点数在典型的Prolog应用中很少,所以不是本文的重点.但是另一方面,整数是在Prolog 中有典型应用场景的(比如记录列表的长度),所以掌握起应用是十分重

Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第二节,数字运算与列表

内容提要 列表中的一些数字运算,累加器 尾递归调用 列表中的一些数字运算,累加器 关于数字运算最为重要的应用,可能是获取一些数据结构体的一些有用事实,比如列表.例如,知道列表的长度是很有用的.我们将会给出一些使用列表和数字运算的例子. 一个列表的长度是多少?这里有一个递归定义: 1. 空列表的长度为0. 2. 非空列表的长度为 1 + len(T),其中len(T)是非空列表的尾部. 这个定义在Prolog中很容易实现,以下是实现代码: len([], 0). len([_|T], N) :-

Learn Prolog Now 翻译 - 第五章 - 数字运算 - 第四节,练习题和答案

练习题5.1  Prolog会如何回答下面的问题? 1. X = 3*4. 2. X is 3*4. 3. 4 is X. 4. X = Y. 5. 3 is 1+2. 6. 3 is +(1,2). 7. 3 is X+2. 8. X is 1+2. 9. 1+2 is 1+2. 10. is(X, +(1,2)). 11. 3+2 = +(3,2). 12. *(7,5) = 7*5. 13. *(7, +(3,2)) = 7*(3+2). 14. *(7, (3+2)) = 7*(3+2)

Learn Prolog Now 翻译 - 第四章 - 列表 - 第四节,练习题和答案

练习题4.1 Prolog将会如何回答下面的查询? 1. [a, b, c, d] = [a, [b, c, d]]. 2. [a, b, c, d] = [a | [b, c, d]]. 3. [a, b, c, d] = [a, b, [c, d]]. 4. [a, b, c, d] = [a, b | [c, d]]. 5. [a, b, c, d] = [a, b, c, [d]]. 6. [a, b, c, d] = [a, b, c | [d]]. 7. [a, b, c, d] =

Learn Prolog Now 翻译 - 第三章 - 递归 - 第一节,递归的定义

在Prolog中,谓词可以递归地定义.简要地讲,一个谓词是递归定义的,如果一个或者多个规则的定义中包含了规则自身. 例子1:消化 考虑如下的知识库: is_digesting(X, Y) :- just_ate(X, Y). is_digesting(X, Y) :- just_ate(X, Z), is_digesting(Z, Y). just_ate(mosquito, blood(john)). just_ate(frog, mosquito). just_ate(stork, frog

Learn Prolog Now 翻译 - 第四章 - 列表 - 第一节,列表定义和使用

内容提要 列表定义: 合一在列表中的使用: 匿名变量: 列表定义 正如名字暗示的,列表就是多个元素组成的集合.更精确地说,是元素的有限序列.在Prolog中的列表,有如下的一些具体例子: [mia, vincent, jules, yolanda] [mia, robber(honey_bunny), X, 2, mia] [ ] [mia, [vincent, jules], [butch, girlfriend(butch)]] [[ ], dead(z), [2, [b, c]], [ ]

Learn Prolog Now 翻译 - 第三章 - 递归 - 第三节,练习题和答案

练习题3.1 在之前的章节中,我们已经讨论了如下的谓词逻辑: descend(X, Y) :- child(X, Y). descend(X, Y) :- child(X, Z), descend(Z, Y). 假设我们将谓词逻辑重构如下: descend(X, Y) :- child(X, Y). descend(X, Y) :- descend(X, Z), descend(Z, Y). 这会导致问题吗? 我的答案: 1. 这个谓词逻辑是有问题的,因为规则2中存在左递归的情况,即规则2的主干

Learn Prolog Now 翻译 - 第三章 - 递归 - 第四节,更多的实践和练习

在学习了前三章内容后,我们应该对Prolog编程有了直观和理性的认识.由于合一.变量初始化.证明搜索和递归都是Prolog的核心概念,所以有如下更多的一些实践和练习. 这里我会先录入题目,后期再给出我自己的程序代码和一些思考. 实践1 试想有如下的描述迷宫的知识库.其中的事实描述了点和点之间的联通关系,即connected/2谓词逻辑给出了这样的事实:迷宫中能从参数1的点,直接到达参数2的点.而且, 联通关系是有方向的.单向不能往返的: connected(1,2). connected(3,4

Learn Prolog Now 翻译 - 第四章 - 列表 - 第二节,列表成员

内容提要 本章主要介绍使用递归操纵列表的一个实际例子:判断一个元素是否在包含在一个列表中. 是时候介绍第一个Prolog中通过递归操纵列表的程序例子了.我们最感兴趣的事情之一是,某个对象是否是列表中的元素.所以,我们想写一个程序,当假设输入是一个对象X和一个列表L, 得出结果是X是否属于L.这个程序的名字通常是:member,是Prolog程序中使用递归操纵列表最简单的例子,如下: member(X, [X|T]). member(X, [H|T]) :- member(X, T). 这就是全部