财新传媒 财新传媒

阅读:0
听报道

兴趣是最好的老师——爱因斯坦

1

最近中国在罗马尼亚大师赛的滑坡,让不少公众对中国最近的禁奥令口诛笔伐,认为是禁奥令直接导致了国际比赛奥数成绩的下滑。但要知道,两年前我国还处在全民奥数的癫狂中,这批参加赛事的孩子可都是在全民奥数的狂热氛围中脱颖而出的,要说和禁奥令有什么直接的因果关系,未免太牵强了。

然而,奥数禁了,家长们的焦虑感并未减轻,总得有某种方式证明自己的孩子比其他孩子优秀,以便让自己的孩子在小升初时占据有利位置。正好,国家提倡人工智能的做法与一些人的需求不谋而合,于是,我们看到了各种各样的机器人、编程课如雨后春笋般迅速地填补了奥数的缺口。

我今天不讨论孩子是否适合学奥数,是否适合学编程。仅仅从师资的角度,现在这一全民编程的趋势比奥数更值得担忧。不管怎样,家长至少都还懂一点小学数学,因此也能够对教学效果有一点点基本的判断;而对机器人和编程,懂行的家长要少的多,因此阿猫阿狗都可以来教编程。要知道,社会上对码农的需求还是很旺的,好的码农能拿到的薪水也是丰厚的。因此,从事少儿编程教学的师资水平的参差不齐程度恐怕要比奥数更甚,建议家长给孩子报编程课尤其要有一双火眼金睛。

 

2

自从学了点Scratch后,昍从去年暑假就嚷嚷着要学C++,我一直干耗着不让他学,这一晃就整整吊了他半年多的胃口,最近终于允许他开始学一点。结果就是,孩子的学习兴趣高涨,动力十足。

其实,虽然没学编程,这半年他一点没闲着,空闲时间整天折腾自己的电脑,从运行病毒把机器搞崩,到装虚拟机在虚拟机里试毒,再到安装双系统,一切都是他自己搞定,甚至整天听的音乐都是熊猫烧香背景音乐。我所能做的就只有三点:一是偶尔告诉他编程能干什么,比如让他着迷的病毒就是一行行枯燥的代码构成的;二是告诉他什么不能做,比如通过email给人发病毒文件是不能做的;三是严格约束他沉迷于电脑的时间,一方面是保护视力,另一方面也是一种饥饿营销。

有人说现在的孩子太苦了,上那么多的课。我不这么认为,很多课是家长强加给孩子的,而且带着极强的功利性。孩子上课外兴趣班,本应能够让孩子发现自己的兴趣,但有些课外班则适得其反,孩子学完反而没兴趣了。昍二年级的时候本来对围棋有点兴趣,于是给他报了个围棋班,但上了一个学期后,他反而没有兴趣了。从此,我后来就没给他上任何兴趣班。有人担心孩子课后不上班是不是就会虚度时间,这可能多虑了。只要控制好游戏和电视,孩子空闲的时间会去真正做一些自己感兴趣的事情,虽然节奏可能会慢一点。给孩子空间和时间,孩子会比我们那时候有更多机会去真正寻找自己真正感兴趣的方向。回想我自己,之前连计算机都没碰过,最后稀里糊涂就选了计算机专业作为自己一辈子的职业,理由只是听闻计算机热。而到最后,也没有当码农,而是follow了自己小学时候的理想:当一名教师。

之前,我一直担心四年级孩子学C++这样的编程语言是不是太早了。经过半个月,我的疑虑一点点地消除了。不仅如此,我发现昍在编程上的潜力可能要超过他在数学上的潜力。昍妈戏说,那是因为我是计算机博士,而不是数学博士。不管怎样,我发现用适当的方法去学点编程,不仅可以对比编程思维和数学思维的差异,还可以让孩子加深对数学与计算的理解。

 

3

有人说数学好编程就好,也有人说编程好数学也差不了。没错,两者有紧密关联,相辅相成,但也有一定的区别。下面是最近和昍一起讨论过的编程书上的几个例子,都是从数学和编程两个角度来引导他思考,也算是一种别样的尝试。

 

1:求1+2+3+4+…+100的和。

数学做法:基本就是等差数列求和,所以是(1+100)×100/2=5050,如果像高斯小时候的同班同学那样死算,势必会被当成傻瓜。

编程做法:我相信包括绝大多数计算机博士在内的都会用下面的程序

int sum = 0;

for(int i=1; i<=100; i++)

       sum += i;

这无疑就是高斯同班同学的做法,但为什么我们不嘲笑这个程序?因为我们通常认为计算机算的非常快,我们需要做的就是告诉它一个明确的计算规则就可以了。

 

2:请给出斐波那契数列1123的第100项。

编程做法:循环+迭代

       int a = 1, b = 1, c;

       int i = 3;

       while(i<=100){

              c=a+b;

              a = b;

              b = c;

       }

孩子需要花一点时间理解迭代的做法。实际上,和之前的求和类似,这也是一种穷举和递推的做法。我们知道计算的递推规则an+2=an+1+an, 为了计算第100项,我们得把前面的每一项都计算出来。

 

数学做法:数学家则远远不满足对这个计算规则的确定,还希望有一个通用的公式能够直接求出任何指定的一项,因此才有了斐波那契数列的通项公式。也正因如此,我们看到了那个著名的黄金分割数。一个整数序列的通项公式,竟然和一个无理数联系起来了。

      

 

3:写出下面程序的输出

int main() {

       int i, j;

       for(i=20, j=0; i<=50; i++, j=j+5)

              if(i==j)count<

       return 0;

}

 

编程做法:看程序写输出一般都是人脑逐步模拟程序的执行,然后从有限步执行推导出程序的功能,写出输出。

这里,i20开始,j0开始,i每次增加1, j每次增加5,当ij相等时输出i的值。因此,执行了5次循环判断后,输出i=25

 

数学做法:如果我们把这个问题按数学的思维来解读一下,j在起点,ij前面20米,j开始追ij每秒走5米,i每秒走1米,请问j追上i时离起点多远?

这就成了一个简单的追及问题,j20÷(5-1)=5秒追上i,此时距离起点25米。

在这里,大家可以看到,数学可以做转化和建模,把一个问题转化和建模为另一个熟知的问题。

 

 

 

4: 在大学校园里,由于校区很大,没有自行车上课办事会很不方便。但实际上,并非去办任何事情都是骑车快,因为骑车总要找车、开锁、停车、锁车等,这要耽误一些时间。假设找到自行车、开锁并骑上自行车的时间为27秒,停车锁车的时间为23秒,步行每秒行走1.2米,骑车每秒行走3.0米。输入距离(单位:米),输出是骑车快还是走路快。

 

编程做法:从编程的角度,任意输入一个距离,那么我们可以分别算出骑车的时间和步行的时间,然后比较一下就可以得出答案。程序基本如下:

int d;

cin>>d;

double twalk = 50+d/3.0;

double tride = d/1.2;

if(twalk

       cout<< “走路快”<

else if(twalk>tride)

       cout<<”骑车快”<

else

       cout<<”一样快”<

 

编程思维就和我们大部分人考虑问题的方式差不多,直肠子,要什么,就求什么。当然,上面的程序之所以说是基本上是这样,是因为还有点小问题。问题在于计算机本身的限制:受制于表示的位数限制,计算机不能精确地存储一个高精度的小数,例如一个无限循环小数或无理数,那么当两个数非常接近时可能会出错。

一个改进的做法是,尽量不做除法。我们可以把twalktride两边都乘以6,得到:

twalk6 = 300+2*d;

tride6 = d*5;

此时,再去比较twalk6tride6会好的多。

      

数学做法:首先分析出一定存在一个临界值x,当距离超过这个临界值时骑车快,而小于这个临界值时是走路快,如果恰好是这个临界值x,那么两者所花时间相等。

可以这么来解读这个题:走路速度每秒1.2米,先走了50秒,然后骑车人开始追走路的人,骑车速度每秒3米,那么骑车人追上走路人时,骑了多少路?

       解这个题,走路先走了60米,骑车人从开始到追上花了60÷(3-1.2)=100/3秒,总共骑了100/3×3=100米。也就是说距离是100米,那么走路和跑步一样快,超过100米,骑车快,少于100米则是步行快。

       可以看到,这里我们又一次把它建模成了一个追及问题。

 

5:为了学生的卫生安全,学校给每个住宿生配一个水杯,每只水杯3元,大洋商城打八八折,百汇商厦“买八送一“。输入学校想买水杯的数量,请你当”参谋“,算一算:到哪家购买较合算?输出商家名称。

编程方法:还是直肠子,任意输入水杯的数量,我们可以先计算出到每个商家购买的总费用,然后比较输出:

       int cups;

       double total;

       cin>>cups;

       a = cups*3*0.88;

       b = (cups – cups/9)*3; 

       if(a

cout<<”大洋商城”<

       else

cout<<”百汇商厦”<

   

数学做法:简单分析一下,买八送一最划算的就是买9的倍数的杯子数,此时能达到最优的折扣,是88.9%。这个最优折扣都比大洋商城来得高,因此不用算,无论买多少个杯子,都是大洋商城划算。

这个小例子体现了数学和工程技术思维的差别。我们投稿一些计算机会议或期刊,即便做了理论分析与论证,有些审稿人也要求做实验验证。隔壁办公室是个做密码学的老师,他们的论文就完全不同,都是证明完了直接结束。实际上确实,数学证明是最严谨的,实验验证还受很多环境的影响,可信度才要打问号。

 

      

6:鸡兔同笼,共有头35个,腿90条,问鸡兔各有几只?

数学解法:五花八门的解法很多,如抬腿法,假设法,方程法等等。

比如假设法,可以假设全是鸡,那么一共有70条腿,比实际少了20条腿,为什么?(能够反问自己为什么是我认为最重要的一种素质)。因为把兔子看成是鸡了。一只兔子假设成一只鸡少2条腿,所以兔子是(90-70)÷2=10只,鸡是25只。

也可以用方程,假设有x只鸡,那么兔子有35-x只,所以得到方程2×x+4×(35-x)=90,解得x=25

 

编程做法:编程可以很暴力。既然共有35个头,那么鸡最少0只,最多35只,枚举一遍逐个验算即可。

for(int i=0;i<=35;i++)

       if(i*2+(35-i)*4==90)

cout << “=”<,兔子=”<<35-i<

可以看到,编程做法更类似于我们数学中的验算。本质上是用方程建模,用枚举求解。

 

7:求1+(1+2)+(1+2+3)+…+(1+2+3+…+10)的值

编程做法:我的第一个想法是用个双重循环,没想到昍第一个想法居然是用下面的一重循环。很明显,这比双重循环更简练。这实际上让计算机少干了不少活,用计算机的术语说,就是计算复杂度(另一个是要考虑的是空间复杂度)降低了。

int i, a=0, s=0;

for(i=1;i<=10;i++)

{

       a=a+i;

       s=s+a;

}

cout<

 

数学做法:按数学思维,一开始就要把这个问题抽象化为1+(1+2)+(1+2+3)+…+(1+2+3+…+n)。一种做法是变成1×n+2×(n-1)+3×(n-2)+…+n(n-(n-1))=1×n+2×n+…+n×n-(1×2+2×3+…+(n-1)×n),后面就不介绍,学过等差和列项应该有所了解。

话题:



0

推荐

昍爸

昍爸

37篇文章 2年前更新

昍爸,曾获初中和高中全国数学奥林匹克联赛一等奖,江苏赛区第一名,高考数学满分,现在大学计算机专业任教,平时注重提升孩子对数学的自我思考与应用能力。此公众号将伴随昍昍的成长,分享寓教于乐、学以致用的数学教育方式。微信公号:昍爸说奥数(xuanbamath)。

文章