AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

程序员最大的遗憾:在大学时忽略了数学

  • 2019-09-09
  • 本文字数:3784 字

    阅读完需:约 12 分钟

程序员最大的遗憾:在大学时忽略了数学

数学重要吗?

数学比你想象的更重要,也比你想象的不那么重要……


你可以忽略数学,你可能只想成为一名高薪的程序员。编程是一个十分广泛的领域,你可以选择你想要关注的领域(其中一些不需要数学知识),并且仍然能够取得成功。但从另外一个角度来看:


  1. 数学是用来解决特殊问题的工具;

  2. 编程就是在做数学。


我想给你们举两个例子,希望能够激励你们给自己一个学习数学的机会。为此,我挑了一些简短(平均 10 分钟)但可能会让你们感到兴奋的视频,用它们来解释这些概念。


但首先请允许我说一些与数学无关的东西……

如果你不想学,就不会去学

在我上大学的时候,我真的不明白学习数学有什么意义。大学的数学和我们在高中学的数学有很大的不同,而我真正想学的是编程。数学似乎只是我获得学位的必经之路,只是为了考试,对我的编程生涯似乎没有任何价值。我固执地认为事实就是这样,所以拒绝在数学上投入很多时间,这导致我第一年被分到一个表现不佳的小组。我太骄傲(应该说是愚蠢)了,但考试有 40%与数学证明有关,我也只是勉强通过考试。第二年我仍然没有改变之前的看法,到最后不得不去参加补考。在补考的时候,我终于妥协了,然后用暑假的大部分时间来学习数学。花了一个暑假,我还是没有学透数学,仍然不明白为什么它这么重要。你可能会认为我会从这次巨大的失败中学到一些教训,但实际上我仍然被固执所蒙蔽。我只想说,如果数学只是一门选修课时,我是不会选它的!但在事后看来,这是我最大的遗憾之一:五年后,我发现我最感兴趣的问题都与数学有着密切的联系。


在递交硕士论文的那一周,我终于拿起一本计算机方面的书。这时,我终于意识到数学和计算机科学以一种非常有趣的方式联系在一起。从那以后,在宝贵的课余时间,我一直在努力赶上那些上课认真听讲的学生。这是一个持续了十多年的过程,而我本可以在大学四年里把这些事情搞定。这十年我本可以把时间花在学习新东西上,就像我的同龄人一样,但我的数学还没有达到研究生水平。有时候我真的觉得我浪费了自己的生命,但与其纠结于此,不如让我们来看一些例子,看看数学对于编程来说有多重要。

数学是程序员的得力工具

游戏和电影中的图形编程涉及到物理知识,但精确的物理模拟是十分昂贵的,所以我们通常使用数学的数值方法来替代,例如使用 Verlet 积分来近似模拟物理:


https://youtu.be/2TIEfgC3tAo


你可能认为谷歌的搜索算法只是简单地计算网页上的单词数量,然后显示具有相关性单词数量最高的页面,如果真是这样,那排名也太容易了,只需要重复地计算单词数量,并不包含任何数学问题。但实际上,对搜索页面进行排名是一个大难题。PageRank 算法考虑到网页之间的链接数,将它们放在矩阵中,然后使用线性代数的特征向量近似算法来计算排名:


https://youtu.be/F5fcEtqysGs


在学习过程中,我发现人工智能(或者说机器学习的子领域)非常有趣。在舞蹈游戏中跟踪手势,在 Netflix 上寻找你可能喜欢的电影,识别当前正在播放的歌曲,等等。如果你想要参与构建这些系统中的任何一个部分,至少需要对微积分、概率论和线性代数有很好的理解。


https://youtu.be/8onB7rPG4Pk


我认为这些例子已经足够了,它们都把数学作为解决特殊问题的工具。现在我想谈谈不那么明显的问题,并解释为什么说数学是就是编程。

编程就是一个吃掉数学的过程

抽象是开胃菜

抽象是编程极其重要的组成部分,我们通过抽象把一个复杂的问题分解成更小的部分。当我们发现了一些模式或者想要隐藏一些复杂性,就会进行抽象,例如使用抽象类或接口。我们甚至为如何抽象和抽象这些模式而创建更高层次的模式。抽象的方式是非常重要的,因为抽象可能会让人感到非常困惑,也可能非常有用。我们如何才能发现最有用的抽象?


尽管计算机只存在了几十年,但计算和计算引擎的设计问题已经存在了几百年。这个事实确实令人感到惊讶,但与数学相比,它仍然只是一个非常年轻的领域,因为数学已经存在了数千年。也就是说,数学拥有更多的时间用来解决某些问题。我们不妨看看是否有可以窃取的想法——事实上,如果不这么,就显得我们有点傲慢!


抽象代数是数学的一个子领域,下面是对抽象代数的一些介绍:


https://youtu.be/QudbrUcVPxk


群是加法和乘法的的抽象,也是幺半群(Monoid)的超类。如果一个组移除了元素需要逆运算的属性,就只剩下幺半群。幺半群是一组元素,包括恒等元素及其关联操作。下面的抽象不仅适用于加法,而且还可以:


幺半群恒等元素运算
整数加法0+
整数乘法1x
字符串串联空字符串concat
扩展列表空列表extend
并集空集合union
布尔类型任意falseor
布尔类型所有trueand
图像重叠透明图像重叠


这个抽象很有用,现在我们就可以编写适用于任何幺半群函数的实现。例如:


  • 一个简单的函数 mconcat,将一系列幺半群元素组合成一个单独的元素,这个时候对整数列表求就变得与重叠图像列表一样。

  • 一个复杂的函数 foldMap,可以递归地遍历树,或者:

  • 返回值为 true 的元素;

  • 找出是否有任何元素大于 5;

  • 将可折叠结构转换为集合。


我们可以进一步抽象,不仅可以将这个函数用于树,也可以用于任何可折叠容器,换句话说,就是任何可以转换为列表的容器。


在设计程序库时,幺半群也是很有用的。如果有一个二元函数,比如乘法,它接受两个相同类型的参数,并返回一个相同类型的结果,这个时候最好要考虑一下哪些是恒等元素。如果找到了,就等于找到了一个非常直观的方法来使用二元函数。你的函数甚至可以处理空列表,因为你有一个合理的带有数学属性的默认值,这将简化用户代码。


在这,我们使用抽象来创建实现,但其实抽象的作用不仅限于此,抽象的作用是解释或发现连接。

组合是主菜

分而治之是人类解决复杂问题的一种非常流行的方法。把问题分解成更小的部分,解决这些小问题,然后把这些解决方案组合成更大问题的解决方案。你能想到另一种更通用的方法吗?


在编程中,我们把一个问题分解成几个较小的函数来解决较小的问题,然后把它们组合成越来越大的函数,最终解决较大的问题。将函数组合在一起的最佳方法是什么?我想知道数学当中是否有我们可以借鉴的想法?


范畴理论是数学的另一个子领域,我喜欢把它叫作抽象的抽象代数,但实际上,它是有关组合的数学。我们可以从中找到很多有用的想法,比如:


  • 函子(Functor),我们可以使用映射函数将函数应用于容器中的每个元素,比如 Python 的 List、Java 的 Stream API 和 Optional,甚至是 Haskell 的函数。

  • 单子(Monad)是 Python List 遍历、C# LINQ、Scala 解析器组合符、Haskell IO 和并发性的基础。我们可以找出任何一种编程语言的的单子。

  • F 代数,我们通过递归进行抽象。


要理解这些抽象的概念可能需要一段时间,所以你开始得越早越好。下面是一个简短的视频,试图解释单子是什么:


https://youtu.be/Nq-q2USYetQ

数学证明是甜点

你们可能还记得我之前说过数学证明是大学数学中最无聊的部分。但我想告诉你的是:类型可以被看作命题,程序可以被看作证明:


https://youtu.be/SknxggwRPzU


以下是一些可证明的属性:


  • x + y = y + x

  • P & (Q | R) = (P & Q) | (P & R)

  • length(filter(predicate, list)) <= length(list)

  • C 编译器生成的可执行代码与 C 程序的语义完全相同,请参见 CompCert(http://compcert.inria.fr/compcert-C.html


现在,我们知道我们可以用编程来证明一些东西,而我发现证明是编程中最有趣的事情。我们因此可以编写更安全、错误更少的程序,因为我们可以证明属性,而不只是测试它们。


但是等等,如果你能用编程来证明一些东西,不是也能通过写程序来为数学做出贡献吗?是的,数学证明不仅对你们来说是难题,对于数学家来说也是难题。数学家总是在证明过程中中制造错误——而这些错误几十年来都没有被发现。同伦类型理论研究的是不同类型的等式,它以单价观点颠覆了数学的基础,认为所谓的数学基础是有缺陷的。是的,即使数学也不是完美的,还有很多需要我们去提升的空间。


我还只是这方面的新手,不过我发现这非常有趣,并且迫不及待地想要学习更多。我可以推荐读者阅读一下 Little Typer(https://mitpress.mit.edu/books/little-typer),它为有递归经验的程序员提供了如何使用依赖类型来进行证明的入门知识。

寻找灵感,打好基础

这似乎是我以前一直在试图不惜一切代价避免的事情,结果却变成了我最喜欢做的事情。所以,不要犯我曾经犯过的错误:充分学好你的数学必修课,否则你以后会后悔的。


如果你的教材不能激励你去探索这一领域的知识,那么可以转向其他的在线资源,比如 YouTube、Coursera 或 Edx,或者试着找一本更好的书。有些人能够将难以理解的概念解释清楚,并激励你——你只需要花点时间去把这些人找出来。你还需要进行练习,就像练习编程一样。


还有一些时候,我也感到很挣扎,因为有些新的概念需要以之前的东西为基础,但我却缺失了这些东西。请不要羞于回头重新去学习之前错过的东西。在数学中,很多东西都是建立在彼此的基础之上,没有坚实的基础,很难取得进步。花点时间回头学习之前错过的东西总是值得的,试着正确地把握这些关键概念,而不是盲目地往前走,让自己陷入一片混乱之中。


我有一个待办事项列表,我用它来弥补之前错过的东西。这只是一个漫长而愉快的旅程的开始。数学是一门庞大而令人兴奋的学科,几乎所有的东西都是相互联系的。我们可以从更大的角度来看待数学:


https://youtu.be/OmJ-4B-mS-Y


原文链接:


https://awalterschulze.github.io/blog/post/neglecting-math-at-university/


2019-09-09 07:076210
用户头像

发布了 731 篇内容, 共 468.6 次阅读, 收获喜欢 2006 次。

关注

评论 1 条评论

发布
暂无评论
发现更多内容

leetcode 135. Candy 分发糖果(困难)

okokabcd

LeetCode 贪心算法 算法与数据结构

亚信科技发布“电信级”核心交易数据库AntDB7.0,助力政企“信”创未来!

亚信AntDB数据库

AntDB 国产数据库 产品发布会

全国首创!洞见科技联合山东数据制定的「数据产品登记」两项标准正式发布

洞见科技

数据 联邦学习 隐私计算

LP单双币质押流动性挖矿系统开发

开发微hkkf5566

Github发布6天,Star55K+,这套笔记足够你拿下90%的Java面试

冉然学Java

java面试 #Github

Go 原生插件使用问题全解析

SOFAStack

Go 语言 开源软件 MOSN 问题解析 开源学习

企事业单位该如何建设知识管理体系

Baklib

跟着官方文档学 Python 之:函数

甜甜的白桃

Python 递归 函数 参数 7月月更

Ceph Swift Api 配置与使用(三)

Lansonli

云原生 Ceph 云存储 7月月更

【都 Java17 了,还不了解 Java 8 ? 】一文带你深入了解 Java 8 新特性

猫的树

java8

【Java 实战】实现大转盘抽奖

猫的树

Java 大转盘抽奖

nacos注册中心之客户端服务注册

急需上岸的小谢

7月月更

系统首页 DIY,你的个性化需求 Pro 系统来满足!

CRMEB

Ceph集群详细部署配置图文讲解(二)

Lansonli

云原生 私有云 Ceph 云存储 7月月更

Windows下Tomcat内存占用过高问题跟踪(jmap 的使用)

源字节1号

软件开发 小程序开发

太奇葩了!Keepalived突发高可用事故

Java全栈架构师

Java 程序员 面试 程序人生 Keepalived

【C语言】进阶指针six

謓泽

7月月更

http请求redirect的问题

飞翔

golang

对象的内存分配一定都是在堆空间吗?

领创集团Advance Intelligence Group

代码优化 内存分配

开源仓库贡献 —— 提交 PR

攻城狮杰森

git GitHub PR 开源贡献 7月月更

数据分析引擎百花齐放,为什么要大力投入ClickHouse?

字节跳动数据平台

java培训之Java8 Stream 代码简化是如何实现的

@零度

stream JAVA开发

web前端培训nodejs异步IO

@零度

node.js 前端开发

NFT数字藏品交易平台APP开发搭建

开发微hkkf5566

大数据培训Hive的数据存储与压缩

@零度

hive 大数据开发

为什么说企业需要具备企业知识管理的能力?

Baklib

【Java 基础你一定要掌握的知识点】Java异常处理和设计

猫的树

Java 异常处理

龙蜥下游发行版 Alinux 和 UOS 成为 OpenSCAP 官方首批支持的国内 OS

OpenAnolis小助手

国产 龙蜥操作系统 UOS v20 OpenSCAP Alinux 2/3

【Docker 那些事儿】关于容器底层技术的奥秘

Albert Edison

7月月更

答应我忘掉Postman吧,Apifox才是yyds!

程序员小毕

Java 程序员 程序人生 后端 开发工具

一道2016年nice的笔试题引发的思考

芒果酱

7月月更

程序员最大的遗憾:在大学时忽略了数学_文化 & 方法_Walter Schulze_InfoQ精选文章