其实,关于C++的各种评价,我已经在之前的某篇文章里讲过了。今天我要从这个话题扩展出来,说一说我对这样一类编程方式的看法。
一 代码与计算机科学
还是那个问题:我们是否应该普遍接触代码?
我的答案是否。我们再换一个问题:
我们是否应该普遍接触计算机科学?我的答案是:是的!
首先,我认为,计算机科学与代码,属于两个不同的范畴。两者之间互相依靠,互相制约,但绝不互相包含。因此学习代码的写法,不等同于学习计算机。因此那些认为学会代码就是懂计算机的人,在我看来,他们的理论非常荒谬。(世界上真正懂计算机的又有几个人呢?)
有很多人认为计算机就是代码,而代码代表计算机。其实计算机科学的学习中真的不需要代码,代码只是一个工具。工具终归是工具,它很难替代使用者本身。
就如你不学微积分,很难进入数学家的圈子,然而却不是学不了数学;你不写代码,只是很难与业内人士装x而已,对于你在计算机科学中的学习,只要找到合适的教程,影响倒真没多少。但是假如数学从微积分学起,那么只能下辈子注意了。
在未来,计算机将普及到每一个普通家庭。将有更多问题依靠计算机解决。届时计算机科学是必不可少的,然而编程语言总有过时的时候,相信现在没几个人主力开发用晶体管网络了吧!100年后,是否还有人在用C++,也是一个未知数。
二 中国式C++
“中国式家长”“中国式学习”等名词,富有中国人民“学习至上”的特别色彩。在这里,我们来谈一谈中国式C++。
我们不妨看一个例子——一个与C++相似的“中国特色”的例子:数学,更贴切的说——“奥数”。
奥数,即奥林匹克数学。一听这个名字就知道,这是一门为了竞赛而生的学科。然而,到了今天,许多家长已经从骨髓中认同这样一个观点:每一个孩子都应该学习奥数。
更有甚者,已经发展出了疯狂甚至有些病态的想法:不学奥数的孩子落伍。
如何评价这样的一群家长?我只能说他们与时俱进。确实,当大多数人都这么认为时,如果你不这么“认为”,你将被淘汰。这就导致了一些课外领域的功利化学习,大概是这么一回事:
为了学而学,目的不是别的,在于能拿得出手。
这里拿得出手,无非就是得个奖,然后告诉别人自己得了奖:好开心!我太nb了!
或者又是:“我们家孩子太菜了,这种竞赛只拿了一等奖!”
或者类似于此的低级趣味。
中国孩子如何学方程?大家都是这么过来的。鸡兔同笼问题的第一课,老师告诉你:假设鸡全是兔子,那么35只兔子有140条腿,因为一共只有94条腿,所以多出了23只兔子——所以鸡有23只,兔子有12只。
随后,老师告诉了你所谓公式。你学会了鸡兔同笼。
就这?
年龄稍长,第二轮学习中,老师又教了你解方程。
会了吗?会了。换了一种题,你又不会做。
而美国呢?我们值得参考的是:他们先让孩子们枚举,随后让孩子们总结规律,最后再把一个强有力的数学工具——方程,教给孩子们。
喜欢套公式是人类的本能。人类正是因为懒得思考才发明了计算机。但是绝不是为了不思考而发明它。
中国式C++,是一个为学而学的体系。我会写代码,我很帅,我很强,我很nb。这就是中国式C++存在的一个原因吧。
三 关于算法
我再次提出之前一篇文章中引用的内容。
很多人认为学校该教孩子们写代码。真的是这样吗?
代码真的重要吗?请问:
-
C和Python有什么区别?
-
在C的语法中,如何定义常量?
-
Python的内置函数是否有JavaScript的保留关键字?
这三个问题值得思考,但是这对你的计算机学习有帮助吗?只是在增加你的烫知识罢了。编程语言有时不是你需要思考的问题。因此,学校不应教学生写代码。如果想学,请去职校。
学校的计算机科学学科又应该教些什么?首先,有这样一段代码:
typedef struct _Range { int start, end; } Range; Range new_Range(int s, int e) { Range r; r.start = s; r.end = e; return r; } void swap(int *x, int *y) { int t = *x; *x = *y; *y = t; } void quick_sort(int arr[], const int len) { if (len <= 0) return; Range r[len]; int p = 0; r[p++] = new_Range(0, len - 1); while (p) { Range range = r[--p]; if (range.start >= range.end) continue; int mid = arr[(range.start + range.end) / 2]; int left = range.start, right = range.end; do { while (arr[left] < mid) ++left; while (arr[right] > mid) --right; if (left <= right) { swap(&arr[left], &arr[right]); left++; right--; } } while (left <= right); if (range.start < right) r[p++] = new_Range(range.start, right); if (range.end > left) r[p++] = new_Range(left, range.end); } }
其实,这就是所谓快速排序算法在C下的实现。请问有谁想用吗?
在我的观点里,计算机科学的发展,就是从与、或、非开始构建体系,再从体系上逐渐增加枝叶。换句话说,计算机科学就是不断地代码复用,复用,再复用。渐渐地,便有了C、Java、Python、Go。
上面那一坨代码,有可能到了以后就长这样:
sort(l)
在我看来,变成这样只是时间问题。毕竟python的内置函数里就有sorted()
。
四 运行效率
有人会说:你这个不成立呀!越来越多的算法被发明,不代表计算机越来越快吗?
说这句话的人,我想他可能也是一个激进的人。这不是不好。但是我觉得,因为人类已经发明了量子计算机,算力是普通计算机的上亿倍,所以算法已经不怎么重要了。即使不用量子计算机,最近马斯克的Dojo,可能也能说明这个问题。
其实这点速度够用就行。0.01秒内,计算机已经能排序出100000个数。在这样的算力下,我们的反应时间早已不够用了,更别提量子计算机了。只要时间可以接受,一切算法皆为可行。
当然,在我看来也有反例。比如质因数分解算法。谁能弄出更快的算法,谁就能把别人的RSA密码破解。这只是一小部分。像大部分的基础算法,有些已经被证明最快,有些只是“足够快”。但是在算力够高的硬件中,我们的算法在一个可接受的时间内能够运行,这就够了。
各位,你们还认为大家都应该普遍功利化学习C++吗?
我在脑海里无数次构想过这样一个计算机世界。这个世界越来越简单,没有所谓“算法”——算法都被极简的模块代替了。没有编程语言,每一个人都用自己的方式做出一个个程序,接入到这个大网络中。我想,这可能在不久的未来会实现。
This post belongs to Column 「不算法专栏」 .
wind
2021-09-12T01:43:43Z那个快速排序是C++的永远的痛……
Itachi
Admin 2021-09-12T04:06:45Z我认为算法本身不可能被替代,极简的模块只是纷繁复杂的算法外面的一层糖衣。必须要有一小部分人会这些算法,否则在可以遇见的将来,再也没有任何人会算法。当未来部分好奇的人们找到这些算法的代码时,一定会感到疑惑,并可能耗上几年乃至几十年的时间来研究这个算法,又开始重新造轮子(reinvent the wheel)。
我认为算法本身是一种思维的训练,这种思维的训练对任何人都大有裨益。更何况,在各种系统的源码中都大量包含了系统程序员们自己实现的为这个系统量身订做的数据结构(可以参考linux中linus手写的高效链表)。如果没有了所谓“算法”,系统的源代码在当今这代维护者逝去后就不再有人能够读懂源代码,我想这种结果是非常悲哀的。
rice0208
Admin Author 2021-09-12T04:44:12Z我认为算法本身不可能被替代,极简的模块只是纷繁复杂的算法外面的一层糖衣。必须要有一小部分人会这些算法,否则在可以遇见的将来,再也没有任何人会算法。当未来部分好奇的人们找到这些算法的代码时,一定会感到疑惑,并可能耗上几年乃至几十年的时间来研究这个算法,又开始重新造轮子(reinvent the wheel)。
我认为算法本身是一种思维的训练,这种思维的训练对任何人都大有裨益。更何况,在各种系统的源码中都大量包含了系统程序员们自己实现的为这个系统量身订做的数据结构(可以参考linux中linus手写的高效链表)。如果没有了所谓“算法”,系统的源代码在当今这代维护者逝去后就不再有人能够读懂源代码,我想这种结果是非常悲哀的。
nononono……我的朋友……我不是指这个意思。
首先,这篇文章面向学生。
然后……就没有然后了。
Itachi
Admin 2021-09-12T04:52:21Znononono……我的朋友……我不是指这个意思。
首先,这篇文章面向学生。
然后……就没有然后了。
面向学生......
我在脑海里无数次构想过这样一个计算机世界。这个世界越来越简单,没有所谓“算法”——算法都被极简的模块代替了。没有编程语言,每一个人都用自己的方式做出一个个程序,接入到这个大网络中。我想,这可能在不久的未来会实现。
你这句话本身好像没有指明面向学生吧🙄,还是我理解有问题🤔?