提到编程,很多人可能会觉得这东西非常高深莫测。但实际上,如果真正尝试就会发现,编程入门并没有想象的那样困难。我在中考结束后的那个暑假就尝试自学了C语言的一些基础内容,又在高一疫情网课期间自学了Python。在我看来,只要你拥有对编程的兴趣,并愿意投入一点时间,完全是可以入门的。
编程到底可以干什么,我们不妨看下面一个例子。还记得初中数学书质数那一章的小故事里提到了所谓的费马数,就是2^(2^n )+1这样的数,费马猜想n取任意自然数的时候这个数都是质数,他尝试了n=0、1、2、3、4的情况,这些数(3、5、17、257、65537)都是质数,但是就凭这个就说后面的都是质数,未免有点太草率了,那么我们怎样才能狠狠地打他的脸呢?不妨算一下n=5的情况吧,这数也不大,不过是2^32+1=4294967297罢了,现在把笔交给各位,验证一下这个数是不是质数吧(逃)
刚刚只是开个玩笑,我们不难发现,验证这个数是不是质数需要相当大量的计算,这显然不是我们手算或借助普通计算器能轻松完成的。但别忘了我们还有一样强大的工具可以使用,我们可以借助计算机,也就是电脑来帮我们计算,我们现在能接触到的电脑(即使是一看就很有年代感的那种),基本上都有一秒钟完成上亿次计算的能力,但是我们该怎么利用这种能力呢?电脑显然没法直接听懂我们的命令,那我们就必须用一种电脑能听懂的“语言”来“命令”它,而Python就是这样一种语言。
我们先来看下面一段Python代码,我们不需要提前具备任何的编程基本知识,只要懂一点最基本的英语(while: 当…时,if: 如果,else: 不然,break: 打破,跳出)并且明白什么是质数,什么是合数就可以了。
为了更方便大家理解,我来做一点简单的说明,首先#后面的内容会被视为注释,也就是给人看的内容,电脑执行的时候会自动忽略掉,也就相当于告诉它: “这不是命令!”。num、isPrime和i都是变量的名称,这里变量的含义和数学中一样,我们也可以用x、y或者任何其他东西给变量命名。while、if和else关键字的含义和英语完全一样,while表示当这一行的条件(上述代码中的i*i<=num)成立时反复执行自己后面的东西,if 则是当条件成立时执行一次自己后面的东西,else则是当前面的if条件不成立时才执行自己后面的东西。这里有一个关键问题:电脑怎么知道一个关键字后面的代码有哪几行是属于这个关键字的,哪几行是无关的代码?事实上,Python用缩进判断哪些东西属于这个while、if或else后面代码块里面的东西,哪些属于外面的东西。每一级缩进都用四个空格来表示。如果这样说比较抽象,那么看看下面这张图,Python代码中缩进所代表的包含关系就像一本书的目录或者正文的分点一样:
这样是不是就很好理解了,上面代码的while循环就是让第5-8行循环执行,而第5行是个if语句,条件成立后执行第6、7行。而第8行的语句无论if的条件是否成立都会被执行。以此类推,9-12行代表isPrime为真时输出质数,否则输出合数。而知道这一点后就可以画出下面的流程图:
明白了这一点后,我们来测试一下这个程序,向它输入4294967297,再回车,我们就会得到:
这个结果几乎是瞬间得出的,就这样,我们只用一眨眼的功夫,就证伪了费马的这一个猜想,我们还可以再试试后面的数,n=5时是18446744073709551617,我们输入进去:
还是瞬间出结果,这样我们知道n=6的情况也是一个合数。
当然,被验证的数越大(准确的说是它除了1以外的最小因子也要很大,判断2^1024这种的是不是质数应该谁都会),计算次数就越多,所需时间也要越长。事实上有一种加密算法就是依靠大数(一般至少512个二进制位,也就是大约154位十进制数)质因数分解的困难性来保证安全的,感兴趣的同学可以搜索RSA算法。
拓展知识:算法的时间复杂度和空间复杂度
算法的时间(空间)复杂度主要是衡量一个算法当输入n增大时,计算所需的时间(内存空间)如何变化,常记为O(f(n))的形式,如O(n^2)、O(1)、O(e^n)。以上面判断质数的算法为例,我们需要对于从2到√num的所有i都进行一次运算(最坏情况下),如果把num看成这个n,那时间复杂度就是O(√n)。注意一下这个复杂度一般只关注一个趋势的问题,是线性关系、幂次关系还是指数关系、对数关系或者什么别的。因此前面的系数我们一般忽略,也就是我们很少说“O(2n)的复杂度”这种话。
当然,如果你觉得这种纯数学的东西没有太大意思,Python能做的也远远不止这些。Python有着丰富的标准库和第三方库,通过调用它们,可以帮助你完成很多非常复杂的事情。例如疫情期间班级里填过体温表,因为大家不太会用共享文档,40多个同学在群里发了各自填好的表格,要把它们一个个打开,再整理成一个很费时费力。而我当时就用Python的openpyxl库写了一个自动化合并Excel表格的工具,可以一键把全班的表格整理成一个。曾经的数学建模小组活动中,我也借用pyQt5库实现了我们建模结果的可视化:
曾经在练习一首歌的时候,我也用过parselmouth库,分析了我录制的自己的干声,再用matplotlib库绘图,直观地看到我哪一个音唱得不准:
此外,我还用ffmpy3库写过一个音视频转码的小工具,通过Python调用ffmpeg.exe完成任意视频和音频的格式转换:
当然,也千万不要觉得这些东西会很难掌握和使用。这些库实现的东西虽然很复杂,但那都是开发这个库的程序员们的事情。他们已经把那些复杂的东西封装起来,只留出非常简洁的“接口”来供我们使用,我们完全不必掌握底层的实现过程,只需要会调用一些基本的方法就行了。关于这些方法,网上也有详尽的官方文档和各种教程供你参考。例如,在我的音视频转换脚本里,最核心的转换工作只用下面几行就能完成。FFmpeg会自动帮你判断编码格式、解码、再编码、输出成文件,而你只需要在现在的文件夹里把转换好的文件复制到你想要的地方就可以了。
如果同学们有学习Python的兴趣和想法,我这里提供一下Python官方安装包的下载链接(直接从python.org官网下载太慢,所以我自己保存了一个,请根据自己电脑的系统选择Windows或Mac版本):
https://cloud.tsinghua.edu.cn/d/9f614878ae774c1db149/
还有环境配置和一些基础语法的教程,可以看下面这个教程:
https://www.runoob.com/python3/python3-tutorial.html
如果在这个过程中遇到任何问题,欢迎通过到我的邮箱提问:smh66ccff@outlook.com,我看到了会尽量解答。
几道思考题,感兴趣的同学可以想想看,也可以发到我的邮箱和我一起探讨:
1.上面计算质数的算法其实是非常笨拙的,你能想到更优化的方法,以减少计算次数吗?(提示:一个都不能被2整除的数还会被4整除吗?)
*2.你觉得上一题中你想到的方法是否降低了时间复杂度?说说为什么?
*3.汉密诺塔问题是一个非常有意思的数学问题和益智游戏,简单来说就是有三个棍子,初始时第一个棍子上穿着一摞圆盘,按照下大上小的规律排列,你需要把所有圆盘移动到最右边的棍子上,要求:(1)每次只移动一个圆盘(2)移动后每个棍子上的圆盘必须仍是下大上小的排列。问对于n个圆盘的情形,最少移动几次?思考一下这个问题怎么通过编程实现。(提示:假如移动n-1个圆盘需要f(n-1)次,那移动n个圆盘所需的次数可以表示为f(n)=?)
文:依韵
发表回复