1.3 用上你训练有素的左脑

本书是为有经验的程序员或在工作中热衷于学习编程的人设计的。为程序员读者写关于数学的内容是极好的,因为如果你会写代码,就已经训练了你的分析性左脑。我认为学习数学的最好方法是借助高级编程语言,并且预测在不远的将来,这将是数学课堂的常态。

对于像你这样的程序员,可以用几种具体的方法来很好地学习数学。我在这里将其列举出来不仅是为了奉承你,也是为了提醒你已经具备了哪些技能,可以在数学学习中利用起来。

1.3.1 使用正式的语言

当学习编程时,第一个痛苦的教训就是,不能像写简单的英文一样编写代码。如果你给朋友写的纸条有少许拼写或语法错误,他们可能还能理解你想说的内容,但代码中的任何语法错误或拼写错误都会导致程序运行失败。在某些语言中,即使在原本正确的语句末尾漏掉一个分号,也会导致程序无法运行。作为另一个例子,看一下下面这两个语句。

x = 5
5 = x

可以把二者都解读为符号的值是5。但这在Python中并不准确,事实上,只有第一条可以如此解读。Python语句x = 5是一个指令,会把变量的值设置为5。但是,不能将数字5设置为具有的值。这可能看起来有些咬文嚼字,但你需要知道这一点才能写出正确的程序。

另一个困扰新手程序员(有经验的程序员也一样)的问题是引用相等。如果定义了一个新的Python类,并创建了它的两个相同的实例,那么它们是不相等的。

>>> class A(): pass
...
>>> A() == A()
False

你可能希望两个相同的表达式是相等的,但这显然不符合Python的规则。因为这两个表达式是A类的不同实例,所以它们是不相等的。

留意新的数学对象,它们看起来像你所熟知的对象,但行为方式却不一样。例如,如果字母代表数,那么。但是,正如你将在第5章中学到的,如果不是数,情况就不一定是这样。如果是矩阵,那么积就是不同的。事实上,它们之中甚至有可能只有一个是合法的,或者两者都不正确。

写代码的时候,仅仅写出语法正确的语句是不够的。语句所代表的思想需要是有意义的、合法的。如果写数学语句时也同样谨慎,你会更快发现错误。更棒的是,如果用代码写数学语句,计算机会帮你做辅助检查。

1.3.2 构建你自己的计算器

计算器在数学课上很常见,因为可以用来检查计算结果。虽然你需要知道在不借助计算器的情况下如何计算6乘以7,但能通过计算器来确认你的答案正确也挺好。一旦掌握了数学概念,计算器还能帮你节省时间。比如在计算三角函数时,你想知道3.141 59 / 6是多少,这可以用计算器很容易地算出来,于是你可以把精力花在思考结果的意义上。计算器能做的事情越多,理论上应该越有帮助。

但计算器有时太复杂了,很难用。当我上高中的时候,老师要求买一个图形计算器。我买了一个TI-84,它有大约40个按钮,每个按钮有两三种不同的模式。我只知道如何使用其中的20个左右。总之,这个工具使用起来相当烦琐。当我在小学一年级拿到第一台计算器时,情况也是一样的。虽然它只有大约15个按钮,但我不知道其中一些是干什么的。如果让我为学生们发明第一台计算器,我会把它做成如图1-14所示的样子。

图1-14 帮学生学习计数的计算器

这个计算器只有两个按钮:一个按钮可以将数值重置为1,另一个按钮可以前进到下一个数。这样“只满足最基本需要”的工具,非常适合帮助孩子学习计数。(这个例子可能看起来很傻,但你确实可以买到这样的计算器!它们通常是机械式的,被当作计数器售卖。)

掌握了如何计数,你就会想练习写整数和做加法了。在这个学习阶段,需要给计算器再加几个按钮(见图1-15)。

图1-15 能写整数和做加法的计算器

在这个阶段,不需要-、×或÷这样的按钮来妨碍你。当你做减法问题(如5-2)时,仍然可以通过这个计算器检查答案(确认3+2=5)。同样,你也可以通过累加来解决乘法问题。摸索完这个计算器后,就可以升级到一个能完成所有算术运算的计算器了。

我认为理想的计算器应该是可扩展的,这意味着可以按需添加更多的功能。例如,可以为你学习的每一个新的数学运算在计算器上添加一个新按钮。当学到代数的时候,也许除了数,还可以让它理解等符号。当你学了微积分时,可以更进一步,使其理解和处理数学函数。

可以处理多种类型数据的可扩展计算器似乎遥不可及,但这正是高级编程语言提供的能力。Python不仅自带算术运算、math模块,还有众多可以随时引入的第三方数学库,让编程环境更加强大。因为Python是图灵完备的,所以你(原则上)可以计算任何可以计算的东西,需要的只是一台足够强大的计算机、一个足够巧妙的程序实现,或者两者兼备。

本书用可复用的Python代码来实现每个新的数学概念。自己动手实现可以很好地加深你对一个新概念的理解。最终,你的工具箱里会多出一个新工具。在自己尝试之后,如果愿意,也可以随时换上一个经过打磨的主流库。无论采用哪种方式,你构建或导入的新工具都为探索更复杂的概念奠定了基础。

1.3.3 用函数建立抽象概念

我刚才所说的过程在编程里叫作抽象。例如,当你厌倦了重复计数时,就可以创建针对加法的抽象;当你厌倦了做重复的加法时,就可以创建针对乘法的抽象;以此类推。

在编程里的所有抽象方式中,可以延续到数学中的最重要的一种方式是函数。在Python中,函数是一种重复执行任务的方法,可以接收一个或多个输入,产生一个输出。例如:

def greet(name):
    print("Hello %s!" % name)

这段代码可以让人用有表现力的简短代码发出多个问候语,比如:

>>> for name in ["John","Paul","George","Ringo"]:
...     greet(name)
...
Hello John!
Hello Paul!
Hello George!
Hello Ringo!

这个函数很实用,但它不像数学函数。数学函数总是接收输入值,并总是返回没有副作用的输出值。

在编程中,我们把行为像数学函数的函数称为纯函数。例如,平方函数接收一个数并返回这个数与自己的乘积。执行时,结果是9。这并不意味着数3现在已经变成了9,而是意味着9是函数在输入为3时的相应输出。可以把这个平方函数想象成一台机器,它在输入槽中接收数,在输出槽中产生结果(数),如图1-16所示。

图1-16 函数就像一台有输入槽和输出槽的机器

这是一个简单实用的心智模型,整本书中都会用到它。我最喜欢它的一点是,你可以把函数当成一个对象来处理。在数学中,就像在Python中一样,函数是可以独立处理的数据,甚至可以将其传递给其他函数。

数学的抽象性会让人望而生畏。但是,就像在任何优秀软件中一样,引入抽象是有原因的:它可以帮助你组织和交流更宏大、更强有力的思想。当你掌握了这些思想并将其转化为代码时,就会开启更多令人兴奋的可能性。

如果你还没有做到这一点,我希望你已经相信,软件开发中有许多令人兴奋的数学应用。作为一名程序员,你已经有了正确的思维方式和工具来学习一些新的数学思想。本书中的思想丰富了我的职业生涯、提升了我的个人素养,希望对你也有所帮助。让我们开始吧!