编程学习的目的是什么,要达到什么程度?

我先给大家讲一个我自己学习数学的故事,再来回答上面的问题。
 
我从中学开始就在老师的带领下准备参加奥赛,但很可惜我一直都没有得过奖。原因嘛,很简单,我脑子不快。我知道某个题我能解答出来,但是我需要时间。那么如果给我足够多的时间,我会怎么解决呢?
 
我做数学题有一个习惯,把自己思考的过程写下来。如果我不详细写下来过程,那个题我就做不出来。
 
我给大家举一个例子:


1)编写calcGCG函数计算并返回两个数的最大公约数。 
2)编写calcLCM函数计算并返回两个数的最小公倍数。 
3)在main函数中首先输入两个正整数a和b,然后调用上述两个函数计算这两个正整数a和b的最大公约数和最小公倍数,最后输出计算结果。 
注意:不要改变函数名称,注意大小写敏感。


 
这个题是我们的同学在C语言课上的一道编程题,要求用C语言来解决,而且时间限制是1000ms,内存限制是256M。
 
我坦承我不是天才,所以这道题我没办法一下子就写出完美的答案来;但我也不是傻子,不会不看题就立刻开始写代码。
 
我会这样把自己的思考过程写下来:
 
一、什么是“最大公约数”?
 
我喜欢在看到中文名词后就去查其英文解释,下面是我在维基百科上查到的:


In mathematics, the greatest common divisor (gcd) of two or more integers, which are not all zero, is the largest positive integer that divides each of the integers. For example, the gcd of 8 and 12 is 4.


 你会发现,“公约数”的英文是“common divisor”,那“divisor”是什么呢?在字典中,“divisor”可以译为“除数”和“因子”。
 
我又去查了以下“divisor”的来源:https://en.wiktionary.org/wiki/divisor
 
发现了如下两个解释:


divisor (plural divisors)

1. (arithmetic) A number or expression that another is to be divided by.

In "42 ÷ 3" the divisor is the 3.

2. An integer that divides another integer an integral number of times.

The positive divisors of 6 are 1, 2 and 3.


 第一个解释非常好理解,在"42 ÷ 3" 这个数学式子中,“3”就像是“三把锋利的刀”,把42分成了三半。“divisor”可以理解成“锋利的分割刀”。我们管这里的“3”叫“除数”,而“42”是被宰的羔羊,所以叫“被除数”。
 
我们再看第二个解释,“an integral number of times”可以理解成“整数次”,也就是说我们要拿刀子来切一个整数,切整数次(没有碎刀,不能切下去就不切),直到不能切为之。所以,“6”先被“1”来切,能切成一个“6”;被“2”来切,能切成两个三;被“3”切,能切成三个二。因此“1”“2”“3”就是“6”的“因子”。
 
这样一理解后,我们就彻底明白什么叫两个数字的最大公约数了:
 
8=1*8=2*4
 
所以:8的“因数”有:1、2、4、8
 
12=1*12=3*4=2*6
 
所以:12的“因数”有:1、2、3、4、6、12
 
在公有的“因数”里,最大的是“4”。
 
维基百科中也有一个例子:

gcd.PNG

 
看完后是不是一下子就清楚什么是“最大公约数”了?
 
可是,为什么“最大公约数”又叫“最大公因数”呢?究竟是“约数”还是“因数”?
 
维基百科里也有解释:The greatest common divisor is also known as the greatest common factor (gcf),[3] highest common factor (hcf),[4] greatest common measure(gcm),[5] or highest common divisor.[6]
 
https://en.wikipedia.org/wiki/ ... visor
 
原来他们其实是一个东西!
 
二、什么是“最小公倍数”?
 
我们继续按照上面的方法去寻找“最小公倍数”的涵义。
 
还是看维基百科的定义:


In arithmetic and number theory, the least common multiple, lowest common multiple, or smallest common multiple of two integers a and b, usually denoted by LCM(a, b), is the smallest positive integer that is divisible by both a and b.[1]


 
有了上面的经验,这一次你肯定会想,“mutiple”又是个什么词?
 
学语言最大的好处就是,可以“睁眼看世界”,去看看英文单词的来源:


(mathematics) A whole number that can be divided by another whole number with no remainder. quotations ▲14, 21 and 70 are multiples of 7
https://en.wiktionary.org/wiki/multiple


 
这下理解了吗?为什么“14”、“21”、“70”都是“7”的“multipe”?因为7复制两次就是14,复制三次就是21,复制10次就是70,另一种称呼的方法就是:7的2倍是14,7的3倍是21,7的10倍是70,所以14、21、70都是7的倍数。
 
我们再看维基百科的例子:


What is the LCM of 4 and 6?

Multiples of 4 are:

4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, ...

and the multiples of 6 are:

6, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, ...

Common multiples of 4 and 6 are simply the numbers that are in both lists:

12, 24, 36, 48, 60, 72, ....

So, from this list of the first few common multiples of the numbers 4 and 6, their least common multiple is 12.


 
如何?这个例子是不是一眼就看出来谁是“4”和“6”的最小公倍数了?
 
三、上面的两个例子有什么启示?
 
上面的例子给我们的启示很简单,要想成为一个聪明的人,就要先花时间打好基础,把基本的知识点搞清楚。大部分人在中学阶段的理科课程中无法往前走出实质性步伐的关键就是:眼高手低,不把基础打好。
 
我这里所谓的“基础”,并非指的是通过记忆记住某些概念的定义。你会发现我在上面的例子中没有去分析定义,而是通过定义去寻找自己不明白的术语,然后找到能够帮助我真正理解术语的直观案例。这些案例就是关键所在。
 
而接下来,我要给大家传授的就是“投机取巧”的走捷径的方法。
 
四、如果第一个轮子不是你发明的怎么办?
 
我这里要给大家讲的是,当你还没有能力去做原创性的工作时,你如何站在巨人的肩膀上去学习。注意:我这里并不是指的抄袭!!!
 
既然你发明不了轮子,那么你就先去看看别人是怎么发明轮子的,至少把别人发明轮子的方法模拟一遍。
 
还是拿上面的案例来讲,既然我们知道了什么是“最大公约数”,什么是“最小公倍数”,那么我们就要去思考怎么去计算两个数字的最大公约数和最小公倍数,有哪些基本的算法。
 
我们可以去网上看一下,你会很容易找到别人给你整理出来的方法,甚至是代码!
 
https://blog.csdn.net/so_geili ... 55291
 
https://blog.csdn.net/keshacoo ... 26637
 
 
比如说,你发现大家都觉得“辗转相除法”是个好方法,那么怎么来实现辗转相除呢?
 
你会发现如下代码:
 
/*题目:输入两个正整数,求其最大公约数。*/

#include <stdio.h>

unsigned gcd ( unsigned,unsigned ) ;

int main( void )

{

unsigned m,n;

printf("请输入两个正整数:");

scanf("%u%u",&m,&n);

printf("%u与%u的最大公约数为:%u\n",m,n,gcd ( m,n ) );

return 0;

}

/* 功能:返回正整数m和n的最大公约数*/

unsigned gcd ( unsigned m,unsigned n )

{

if (m<n)

{

int temp=m;

m=n;

n=temp;

}

if ( m % n == 0) {


return n;

}else{


return gcd ( n,m % n) ;

}

}
在这段代码中,假如你从来没有学过C语言,要想看懂这段代码,“拦路虎”有哪些?
 
1. unsigned是什么?
2. void是什么?
3. %这个符号的作用是什么?
4. =和==有设么区别?
5. printf和scanf的区别是什么?
 
同学们,请问这些“拦路虎”的本质是什么?
 
这才是我要给你们说的“捷径”:在案例中发现那些阻拦自己前进的基础知识,一些你必须死记硬背才能根植于心的基础知识。无论是别人用的算法,还是别人用的函数,还是别人用的各种符号,都是一个人对基础知识的组合。
 
五、现在我们再来说说编程
 
如果你突破了每一个编程语言的“基础知识”,那么我可以非常肯定得告诉你,作为一个翻译专业的学生,你学习编程的目的已经达到了,因为我们在做翻译时,最重要的一步就是读懂原文,否则你是不可能把译文正确表达出来的。
 
但是,最为一个文理兼修的学生,你还要继续往前走,你要能自己操控代码去解决问题。因为只有在解决问题的过程中,你才能不断磨练自己的心智和思维,让自己成为一个会使用技术工具解决问题的人。这个时候的你会发现,学什么编程语言不重要,你曾经用编程语言解决过什么问题不重要,就好像“学步车”是你学习走路时的重要辅助工具,一旦你学会走步后,你就不再需要了。抑或是火箭发射时的“助推器”,没有它万万不行。
 
你在学习编程的过程中,不由得会形成一种新的思维方式,有些人管这个叫“计算思维”,一种解决问题的科学的思维方式。在我看来,这种思维方式给你带来的是一种全新的高效的学习方式,让你能够成为一个能够利用科学的方式快速学习的问题解决者。
 
有了科学的思维方式和快速的学习能力,不管你去做什么、学什么,你接下来最迫切需求的就是场景、问题描述和解决问题所需的素材。
 
比如:如果你想用机器翻译来辅助口译人员提升翻译的质量,场景是什么?你需要哪些素材?你要解决的究竟是什么问题?
 
同学们,无论是编程,还是翻译,都是工具,学习工具的过程本身是耗费时间、耗费精力的,所谓“无他,唯手熟尔”,练手的过程总是乏味无趣的,但成长的过程就是要有这样的煎熬。
 
我在这篇文章中给大家讲的就是当我们在生理上不具备天生的“速算、心算”的能力时,我是如何通过一行行的文字记录我的思考和推理过程,直到把题目最对。我能够告诉你们的就是如何在生理上天生不如别人的时候,如何“业精于勤”。
 
希望对大家有些许启发。
 
PS:再用一个做翻译的例子给大家一些更多的启发:
 
“地板除”还是“取整除”? —论程序员是如何被翻译误导的
 
https://mp.weixin.qq.com/s/aoRKUtx9fOmTjCn_Kzun0A
 

2 个评论

为什么有时候我会说翻译专业的学生到了研究生阶段再学编程就有些晚了呢,主要原因还是本科的时光最长最轻松,到了研究生阶段时间就真得是越来越少了,能静下来学知识磨练本事的时间也越来越少了。
想沉淀,才读研。读研却发现时间更紧张....

要回复文章请先登录注册