自然数的概念直接来自人们的生活,但数学家们为自然数N建立了完整的公理体系。皮亚诺公理就是接受最广的一个。
我们这里使用扩展的自然数(即包含了0的自然数)
- ①N中有一个元素,记作0。
- ②N中任一个元素都能在 N 中找到一个元素作为它的后继者。
- ③0不是任何元素的后继者。
- ④不同元素有不同的后继者。
- ⑤(归纳公理)N的任一子集M,如果0∈M,并且只要x在M中就能推出x的后继者也在M中,那么M=N。
让我们来自己动手实现一个单纯的自然数系统N。
为了避免和我们习惯的数字混淆,我们将完全不使用任何程序中的数字变量。
- ① 对于0元素,我们用None表示,通过函数zero获得。
- ②任何元素都有后继,我们用一个函数nNext来获得它。
- ④不同元素有不同的后继,用一个函数nPre来获得某个元素是谁的后继。
- ③0不是任何元素的后继,所以nPre(zero())将报错。
- ⑤上面四条公理已经足够建立起自然数的框架,最后的归纳公理将用来建立整个比较和运算体系。
我们首先看关于0的定义,用两个函数来实现:
# 返回特例数字“0”,其特点是它不是任何数字的后继
def zero():
return ['自然数的起点','零']
def isZero(a):
return a==['自然数的起点','零']
zero()获得特例数字0,这个0,可以用任何内容来代表。唯一的关键是我们有办法用isZero()函数判断它是0即可。
为了这一原则显得更加明显,我们这里特意用了比较复杂的表示:用一个含有两个元素的列表来代表这个0。
接下来是后继与前驱的实现,也用了两个函数:
# 返回a的后继
def nNext(a):
def number(cmd):
if cmd== 'pre':
# 只知道前驱是a
return a
else:
# 其他一概不知
return None
return number
nNext()这里涉及一点高阶函数的知识。构造了一个函数,用这个函数来代表数字。这个函数接收一个参数,当这个参数是"pre"的时候,返回这个数字的前驱,显然是为了给下一个函数nPre使用。除此之外,任何其他的参数都返回None,代表一无所知。
# 返回a的前驱是谁(a是谁的后继),这也是a唯一知道的事情
def nPre(a):
if isZero(a):
raise TypeError
return a('pre')
nPre()除了数字0报错之外,其余的数字,直接返回它的前驱,很明确。
在后面的课程中,我们将从这几个看似简单的基本函数开始,构建起完整的算术框架。我们将深刻地理解,我们日常所使用的数字背后其实真的只有几条公理而已。