本文并非试图给迷茫的初学者提供一个一站式的“宝宝巴适”学习计划(这样的学习计划有很多),而是想尽可能地给读者以丰富选择——全景式地展示计算机科学中的方方面面,(尝试)给出各个学科的学习资料、自学路径。
如果仍需要一个最快、最短、最功利主义的学习路径,那么以下是你需要完成的主线任务:
不妨在学习这些内容时再来回看本文,逐步开拓视野,探索支线任务。
加★的资源为高质量推荐资源或该领域的经典之作,但并非一定适合初学者、适合自学。请根据自身情况和学习目标有选择地选析。
很多人都被计算机科学吓倒了,甚至50%以上的名校计算机专业毕业生都达不到入门,这是因为:
天才也非不学就会——学习任何知识,无论是计算机,还是数学、物理等理论性抽象性很强的学科,都像柯南探案一样,只有在了解了A、B、C、D所有的线索之后,才能自然而然地理解整个事件的原貌,缺一不可。反之,如果你感觉学不会,那就是还欠缺了许多的前备知识,“胜利的拼图还没集齐”。(数学第一定律)无论是牛顿、高斯、伽罗瓦、爱因斯坦,他们都不是从0开始创造了所有的理论,原创的只是少数——他们通过学习获得的知识体系的量大大超过了他们原创的数学方法。正确地选取学习顺序、不因一时地挫败而情绪化地自暴自弃非常重要。
入门计算机科学的传统方法,通常是学习一门类似于“信息技术基础”的课程,但这门课十分鸡肋,既不能直观地展示出计算机专业的特点,而因其深度太浅,单纯地铺开学习广度无法深入人心,就像在给学生远远地观看甲骨文上的卜辞。
如果你熟悉计算机的基础操作,一个稍显硬核的方法是,直接去学习一门编程语言,学会与计算机对话。便捷的编程工具让这成为了现实。
不要害怕自学——就像“不自量力”的真正解释是,“不自学学不好量子力学”,计算机科学的最佳学习方法也是自学。甚至可以说,没有相当程度的自学能力,是不可能学会计算机科学的!计算机科学本身就是一个涉及非常广泛的综合学科,而面向不同的工作领域,又会遇到不同的技术的组合(技术栈)。学习时一蹴而就、工作中仅仅依靠“吃老本”断不可行。
一定要做编程作业——计算机科学课程的最大特点是:做课后作业的编程项目比听课、读教材重要得多,这是最能透彻学会一门技术的方法,也是效率最高的方法。一般而言,在公开课的主页都可以找到配套的课后作业,这些作业质量极高,并且可能配有答案。在Github上也可以搜到
于是紧接而来的问题是,如何选取自己的第一门语言?其实这个问题无关紧要‵
我遇到过很多偏执迂腐的人,他们在对计算机科学一无所知的情况下,不断重复着“刻板偏见”,无视那些真正有益的建议。
另外一个令人哭笑不得的蠢事是:编程语言已经形成了各种宗教教派(多么讽刺!用愚昧无知的宗教迷信去敬拜人类科技中的瑰宝)。时下Python的教徒最多,他们因为人工智能应用的泛用而获得了莫大优越感,攻击其他语言赶不上潮流(人工智能绝非Python独享)。C语言的信众是最古老的,他们的兴起仅仅是因为恰巧——Unix恰巧变得流行,Unix恰巧是用C语言编写而成。
人类发明了数千种编程语言,似乎永远也学不完——但事实是,其实(主要)只有四种编程语言的“思想”(严格来说,是范式Paradigm),也就是人类操控计算机有四种思想;同类编程语言之间的差异极小,比东北话和北京话、利物浦口音和伦敦腔差距更小(前提是,你透彻地理解了编程语言的本质)。这四类是:命令式编程、面向对象编程、函数式编程、逻辑式编程。
这四种编程范式,才是最核心的组织计算机程序的方法,是每一个程序开发人员需要深刻理解的思想(而不是泡在层出不穷的新语言的汪洋大海中);编程语言固然重要,但是也只是这四种思维的表达形式、是外表而非筋骨(这也是为什么中文编程毫无意义,编程的真正语言是高度抽象的数学语言,而而非英文或者中文)。现代编程语言总是想给你很大的自由(大部分语言是多范式的),所以只要去学就好了,你永远可以十分轻松地从一门编程语言切换到另外一门。
与其挑剔编程语言,不如选取更容易理解的公开课和教程。以下是非常适合入门的编程语言学习资源。
Python是当前最炙手可热的编程语言,其设计注重简洁、可读性和易用性,使其成为初学者入门的理想语言。Python的最大优势为:
Scheme是Lisp语言的方言之一,具有语法非常简洁,拥有少量的基本语法规则和表达式结构的特点。Scheme作为一种纯粹的函数式编程语言,将函数作为第一类对象,即“一切皆函数”,以Lambda演算为基本的计算模型。学习Scheme语言可以更直接地用计算思维组织程序,也可以接触到动态类型系统、宏系统、高阶函数、闭包、反射、元编程等“高级”编程特性。
Haskell是一种纯函数式编程语言,具有强大的类型系统和高级特性。它由米兰·昆德拉等人于1987年设计开发,旨在提供一个优雅、安全、可靠且高效的编程环境。Haskell鼓励纯函数式编程,采用静态类型系统、惰性求值策略,支持高阶函数和函数组合,具有强大的并发和并行编程能力。
一个几乎对于所有学科通用的“初窥门径”的方法是,学习它的历史。了解了一个学科的诞生初期的模样,可以清楚地看到这门学科是从哪些基础思想演化而来,而又是为了解决什么困难的问题而被创造;再结合后续的发展,可以将多端寡要的现状与远古时期的单一直接的目的连接。
不要急功近利——你可以从“科普”“奶头乐”开始,不需要一开始就给自己“上强度”。只要沉浸进去就会发现,计算机科学真的很有趣,兴趣可以推动你走下去。
如果去问一个学者、教授、工程师,他们的职业生涯最后悔的地方是什么,他们往往会说,“在学生阶段没有打好基础。如果可以重来,我一定要把哪些基本的课程一点点学明白”。基础对于任何学科都尤为重要,在计算机科学更是如此。
计算机科学的基础最核心的部分包括离散数学与概率论、算法、计算机网络、操作系统、数据库和计算机组成与结构,是系统性地学习计算机科学必不可少的重点内容。这部分内容学起来比较枯燥乏味,有一定的抽象性,和日常生活的距离非常远,很容易使人因身在庐山中而不识真面目。
这个阶段往往是学习计算机最艰难、最困惑的时刻。以下是一些学习建议:
使用英语——至今为止,英语仍然是计算机科学的主流学术语言,英语互联网中的学习资源无论是质量还是数量都百倍于中文互联网——这不是崇洋媚外,在客观定论之前,一切民族主义冲动和独断论都显得缺乏智慧。最新的技术著作、最新的学术论文、最好的网络课程资源,几乎都由英语写作而成。并且,即使那些著作被翻译成了中文,其理解难度也高于直接看英文原版。这有两部分原因:a.许多技术的英文专有名词更接近直觉和生活,理解成本低,而中文则被翻译成了专有名词,需要专门解释、专门理解;b.中文翻译的质量参差不齐,往往存在很多句不达意、翻译错误、机翻的情况(请不要责怪译者,翻译计算机书籍纯属“为爱发电”,费力不讨好,几乎没有经济利益)。
克服英语阅读障碍最好的方式是翻译一本有价值的书。
操作系统是计算机硬件与应用软件之间的桥梁,负责管理和协调计算机系统的各个部分,以提供用户和应用程序所需的服务。有一个很好的比喻是,操作系统在启动后,“静静的趴在内存里”,等待应用程序在需要时调用。
操作系统是计算机科学中的一门基础课程,目标是理解计算机系统中操作系统的重要作用,以及如何管理和协调硬件和软件资源。一般包括:进程管理、内存管理、文件系统、输入/输出系统、系统调用和系统服务、死锁、安全性和保护、分布式操作系统等话题。
计算机网络课程涵盖计算机科学和工程领域中有关计算机网络的基本概念、协议、技术和应用的内容。这门课程的目标是使学生了解计算机网络的原理、设计和管理,以及网络通信中涉及的各种技术和协议,包括TCP/IP协议族、HTTP、DNS等。
在计算机科学的教育和实际应用中,数据结构与算法的学习是重要的基础。它们为程序员提供了解决实际问题的工具和方法,是编写高效、可维护和可扩展软件的关键要素。数据结构与算法是计算机科学中两个基础而重要的概念。
数据库是一个结构化的数据集合,用于存储、管理和组织数据。它是一个电子化的文件柜,可以容纳大量有关特定主题的数据,方便在需要时读取已有的数据、添加新的数据,或者进行一些数据的管理。
计算机科学中数学的重要性众说纷纭,它们的问题在于,妄图以自己片面的认知代表整个学科。
所以可以看到,学计算机科学需不需要数学,这个问题本身就不是一个单一的问题——但是却可以有一个单一的解答:你需要根据自己所深入学习的领域,来决定自己究竟需要哪方面的数学基础。
离散数学是数学的一个分支,它研究离散对象和离散结构,通常涉及不连续、离散的整数值或离散集合。离散数学与计算机科学的关系如下:
概率论研究随机事件发生的可能性,包括样本空间、事件、概率分布、条件概率等基本概念。它提供了一种描述随机现象的框架。统计学涉及收集、分析、解释和呈现数据的方法。它使用概率论的概念来进行推断和决策。概率论与统计学在计算机科学的以下领域发挥作用:
线性代数是数学的一个分支,研究向量空间和线性映射的代数结构。线性代数的概念和技术在计算机科学中被广泛应用。
计算思维是计算机科学中的一种思考方式,强调问题的抽象化、问题的分解、模式识别以及算法设计和评估。它是一种将计算机科学的概念和原则应用到解决问题的思考方法。
★【书籍】(CSAPP)深入理解计算机系统ComputerSystems:AProgrammer'sPerspective
分布式系统是由多个独立的计算机或服务器组成的系统,这些计算机或服务器通过网络相互连接和协作,以实现共同的目标。分布式系统的主要特点是它们分布在多个地理位置,并且可以同时处理多个任务或请求。
分布式系统广泛应用于各种领域,包括云计算、大数据处理、物联网、分布式数据库、分布式存储和分布式计算。它们提供了高可用性、高性能和可扩展性,使得复杂的任务和大规模计算成为可能。但同时,分布式系统的设计和管理也面临许多挑战,如数据一致性、容错性和性能优化等。因此,分布式系统的开发和维护需要深入的专业知识和技能。
并行计算是一种在多个处理单元上同时执行计算任务的计算模型,旨在提高计算速度和处理能力。本课程主要讲授使用并行计算的多核处理器和多处理器系统、SIMD(单指令多数据)和MIMD(多指令多数据)架构,并行编程模型、并行算法以及并行性能分析和优化、任务调度和负载平衡、并行编程语言和工具。
高阶数据库课程通常针对数据库理论和技术的深入学习。这些课程旨在扩展学生对数据库管理系统(DBMS)的基本概念的理解,并介绍更高级的主题,包括数据库设计、查询优化、事务管理、数据仓库、数据挖掘和数据库安全等。
【课程】CMU15-799:SpecialTopicsinDatabaseSystems
Linux是一种流行的开源操作系统,它是基于Unix的多用户、多任务的操作系统。Linux最初由林纳斯·托瓦兹(LinusTorvalds)于1991年创建,现在由全球的开发者社区共同维护和开发。它以其稳定性、安全性和灵活性而闻名,并被广泛应用于服务器、桌面、移动设备、嵌入式系统等多种环境中。
版本控制工具Git——Git是一个开源的分布式版本控制系统,当前最流行的源代码管理工具之一,被广泛用于软件开发和其他版本控制任务。
**集成开发环境(IDE)**是软件开发中的一个重要组件,它集成了多种工具来协助程序员进行高效的编码、调试和测试。
选择适合自己的IDE:使用取决于多个因素,包括你的编程语言、项目类型、个人偏好和特定的功能需求。以下是一些在选择IDE时可以考虑的关键因素:
Docker是一种开源的容器化平台,它允许开发者将应用程序及其依赖打包在一个轻量级、可移植的容器中。这些容器可以在任何支持Docker的机器上运行,从而确保应用程序在不同环境中的一致性和可扩展性。Docker在2013年首次发布,迅速成为容器化技术中最受欢迎的平台之一。Docker的主要特点和优势包括:
C语言是一种通用的高级编程语言,由DennisRitchie在1972年于贝尔实验室开发。它为程序员提供了很大的控制权,但也需要谨慎处理内存和指针,以避免潜在的错误。因此,C语言对于那些希望深入了解计算机编程的人来说是一门重要的语言。它是一种强大的编程语言,广泛用于系统编程、嵌入式编程、应用程序开发和游戏开发等领域。
C++是一种高级编程语言,由BjarneStroustrup在1980年代初期开发,作为C语言的扩展。C++添加了面向对象编程等特性,同时保留了C的效率和灵活性,使其成为系统软件、应用软件、高性能服务器和客户端应用程序、以及性能敏感的游戏和实用程序的常用语言。C++支持面向对象编程,包括类、继承、多态、封装和抽象。
CommonLisp是Lisp编程语言家族中的一种方言,是一种多范式的编程语言,以其强大的宏系统、动态类型和交互式开发环境而闻名。CommonLisp起源于1980年代,是基于几个早期Lisp方言(如Maclisp、Zetalisp和NIL)的特性和思想开发而成的。它是Lisp语言的一个标准化形式,并且是目前最完整和最强大的Lisp方言之一。
Coq是一个形式化证明管理系统,用于帮助编写数学证明并验证这些证明的正确性。它是一个交互式定理证明器,允许用户定义数学概念、表述定理,并通过一系列逻辑推理构造证明。Coq在数学和计算机科学领域都非常有用,特别是在那些要求高度精确和正确性保证的领域。
Erlang是一种高级编程语言,最初由爱立信公司在1980年代为支持大规模的并发、分布式系统而开发。它最初是设计用于在电信系统中处理大量并发活动的,但后来被广泛应用于构建可伸缩、高可用性的服务器系统和分布式应用程序。
【书籍】LearnYouSomeErlangforGreatGood!:ABeginner'sGuide
Haskell是一种纯函数式编程语言,拥有一个非常强大且灵活的强类型系统,支持高级特性,如类型推断、泛型编程和类型多态。Haskell默认采用惰性求值(LazyEvaluation),这意味着表达式的值仅在需要时计算。Haskell引入了类型类(TypeClasses)的概念,它是一种表示一组类型共享某些行为的方式,类似于其他语言中的接口。Haskell提供了模式匹配和列表推导等强大的语法结构,使得代码更加简洁易读。Haskell支持多种并发和并行编程模型,包括软件事务内存(STM)。
Idris是一种相对较新的纯函数式编程语言,特别强调依赖类型(DependentTypes)的使用。这种强类型系统允许类型依赖于值,比传统的类型系统更强大,可以在类型级别上编码更多的逻辑和属性,使得程序员可以编写更加精确和表达丰富的程序。Idris的设计旨在支持纯函数式编程,同时提供强大的类型检查,以帮助开发者构建更加安全和可靠的软件。Idris提供了自动类型推断功能,可以减少编写类型注解的需要,同时保持代码的类型安全。
【书籍】ProgramminginIDRIS,ATutorial
【书籍】Type-drivenDevelopmentwithIdris
【书籍】EffectiveJava
【书籍】CoreJava
JavaScript是一种动态类型的多范式的编程语言(事件驱动、函数式、面向对象),最初由Netscape的BrendanEich在1995年设计。尽管它最初被创建为网页浏览器中的脚本语言,但如今它已发展成为一种广泛用于客户端和服务器端的通用编程语言。JavaScript是构建现代网页和网络应用的核心技术之一,与HTML和CSS一起构成了万维网的三大支柱。
【书籍】JavaScriptProgrammer'sReference
Javascript的命名据说是开发者蹭Java的热度而来,两者关系甚微。
Kotlin是一种现代的静态类型的编程语言,由JetBrains公司在2011年首次发布。它被设计为完全兼容Java,并能在Java虚拟机(JVM)上运行,但在语法和功能上进行了现代化的改进。Kotlin的目标是提供一种比Java更简洁、更安全且更表达性的语言,同时保持与Java的高度兼容性。
【书籍】FundamentalKotlin
MATLAB(MatrixLaboratory的缩写)是由MathWorks公司开发的一种高性能的数值计算和可视化编程环境和语言。自1984年推出以来,MATLAB已经成为科学、工程和数学领域中广泛使用的工具之一,特别适用于矩阵运算、算法实现、数据分析、信号处理和图形可视化。
【书籍】MATLABPrimer
OCaml(ObjectiveCaml的缩写)是一种高级编程语言,是Caml语言的最新版本,由法国国家信息与自动化研究所(INRIA)开发。其特点为:强类型、采用静态类型系统,拥有灵活的模块系统,结合了函数式编程、命令式编程和面向对象编程的特性,提供了一个快速而有效的编译器以及丰富的库。
Prolog(ProgramminginLogic的缩写)是一种高级编程语言,主要用于逻辑编程范式。Prolog特别适合于处理符号和非数值计算的问题,常用于人工智能和计算语言学领域。其特点为:
Racket是一种多范式的编程语言(函数式、命令式、逻辑式和面向对象编程),最初是为了教育和研究而设计,但现在它也被广泛用于工业和商业应用。Racket最初基于Scheme,后者是Lisp家族的一个成员,因此它继承了Lisp的许多特性,如其强大的宏系统和简洁的语法。Racket的设计哲学鼓励创建新的编程语言和工具,作为解决特定问题的方式。Racket有一个庞大的标准库,提供了从图形界面到网络编程的各种功能。
Rust是一种现代编程语言,专注于安全性、速度和并发性。它由MozillaResearch开发,旨在提供C++等系统编程语言的性能,同时确保更高的安全性和更易于管理的代码结构。
Scala是一种多范式的编程语言(支持面向对象和函数式编程范式),设计用来表达通用的编程模式以简洁、优雅和类型安全的方式。它集成了面向对象编程和函数式编程的特性。Scala运行在Java虚拟机(JVM)上,因此它与Java有很高的兼容性,可以直接使用Java的类库。
计算机代数系统(ComputerAlgebraSystem,简称CAS)是一类专门用于执行符号计算的软件系统。符号计算是指对数学表达式中的符号进行操作,而不是仅仅进行数值计算。这些系统能够处理代数表达式、方程、多项式、矩阵等符号形式的数学对象。
计算机代数系统可以执行诸如化简代数表达式、解方程、求导、积分、展开多项式、因式分解等符号计算操作。这使得它们在数学、科学工程、计算机科学等领域中得到广泛应用。
主要的计算机代数系统包括:
凸优化是数学和计算机科学中一个重要的领域,主要研究凸函数的最优化问题。凸函数是一类具有良好性质的数学函数,其图形上的任意两点之间的线段位于或者在函数的下方。凸函数在许多领域中都具有重要的应用,因此对凸优化的研究也变得非常重要。
【书籍】人工智能:一种现代方法ArtificialIntelligence:AModernApproach(AIMA)
“数据科学”是一门涉及从大量数据中提取信息、洞察和知识的跨学科领域。数据科学将统计学、机器学习、计算机科学和领域专业知识相结合,以分析和解释复杂的现实世界数据。
“机器学习”是人工智能的一个分支,研究计算机系统如何通过学习和经验改进性能。机器学习的目标是使计算机具有从数据中学习的能力,而无需显式地进行编程。机器学习的主要任务是设计和开发算法,使计算机系统能够利用数据进行学习、预测和决策。
“深度学习”是机器学习的一个分支。它专注于使用“深度神经网络”进行模式识别和特征学习。深度学习的目标是通过模拟人脑神经元网络的方式,使计算机能够从大量数据中学习和提取复杂的特征,以进行任务如分类、识别、推理等。
大语言模型(简称LLM)是指使用大量参数和深度学习技术构建的自然语言处理模型。这些模型在处理和生成自然语言文本方面表现出色,能够理解语言的上下文、语法和语义,并生成具有流畅性和逼真性的文本。
“强化学习”是机器学习的一个分支,专注于研究智能体(agent)如何通过与环境的交互学习行为以达到某种目标。在强化学习中,智能体通过尝试不同的行动来最大化累积的奖励,而不需要显式的监督信号或预先标记的数据。
“自然语言处理”是一门研究如何使计算机能够理解、解释和生成自然语言的学科。自然语言是人类用于交流的语言,包括语音和文本。NLP的目标是开发算法和技术,使计算机能够处理和理解人类语言的各个方面。
计算机视觉是一门研究如何使计算机系统能够模拟和复制人类视觉系统功能的学科。该学科涉及开发算法和技术,使计算机能够理解、解释和处理图像或视频数据。计算机视觉的目标是使计算机具备类似于人类视觉系统的能力,包括对物体、场景、运动等进行感知和理解。
“专家系统”是人工智能领域的一个重要分支,专门研究如何构建能够模拟和复制人类专家知识与决策能力的计算机系统。
“知识表示”是人工智能领域的一个重要概念,涉及将现实世界中的信息以某种形式表示出来,以便计算机能够理解、存储和处理这些信息。知识表示旨在捕捉关于世界的知识,使计算机能够使用这些知识进行推理、问题解决和决策。
“机器人学”是涵盖了多个学科领域的综合学科,主要研究设计、制造、操作和使用机器人的原理、技术和应用。
软件工程是一个综合性极强的学科,主要包含了以下主题:
移动应用开发是为智能手机、平板电脑和数字助理制作软件的过程,最常见的是针对Android和iOS操作系统。这些应用可以提供各种功能和服务,从社交媒体和游戏到生产力工具和电子商务应用。软件可预装在设备上,可从移动应用商店下载,也可以通过移动Web浏览器来访问。
移动应用开发、桌面应用开发、网站开发都需要培养一系列相辅相成的开发能力——统称为技术栈(TechStack)。具体来说,就是在开发中所使用的一组技术、工具和框架的组合。在生产实践中,往往可以由一个团队合作,每个个体只参与其中的一环;但也有很多人通晓开发的整个步骤,并有很高的效率,这些人被称为“全栈工程师”(FullStackEngineer)。全栈工程师有能力参与从应用程序的用户界面设计到服务器端编程以及与数据库交互的整个开发过程。
在生产实践中,不同应用都有一个特定的技术栈,其中的技术很可能并不先进、并非最优,而是过去时代的遗留。人类不可能全部掌握浩如烟海的这些技术、工具和框架(虽然具有很高的共通性)。所以在学习这部分内容时,掌握其涉及的基础技术(如HTML/CSS、编程语言、数据库系统、计算机安全、测试和调试、用户界面设计等),并了解和学习一个典型的技术栈就足够了。
“桌面应用开发”是指为桌面操作系统(如Windows、macOS或Linux)设计和创建应用程序的过程。与为移动设备或网页开发的应用程序不同,桌面应用通常具有更丰富的用户界面和功能,能够充分利用计算机的处理能力和资源。
Windows应用开发的主流技术(截至2023):
Mac应用开发的主流技术(截至2023):
Linux应用开发的主流技术(截至2023):
网页开发技术栈的示例:
计算机安全课程通常涵盖以下主题:
离散优化是指在离散的领域中寻找最优解的问题。这些问题通常涉及到在有限的选择中作出最佳决策的情境。离散优化领域包括许多不同类型的问题,其中一些常见的包括:
“软件测试”是一门涉及计算机科学和软件工程领域的课程,旨在教授学生如何有效地进行软件测试和质量保障。以下是这门课程可能涉及的主题:
“用户界面设计”是一门涉及计算机科学、人机交互和用户体验设计的课程,旨在教授学生如何创建用户友好、直观且有效的软件界面。
以下是“计算机图形学与混合现实在线平台(games-cn.org)”提供的一系列关于计算机图形学和虚拟现实的课程。
“游戏开发”是一门涉及设计、编程和艺术等多个领域的课程,专注于培养学生创建电子游戏的技能。这门课程通常包括以下主题:
“形式语言”是一种用于描述、表示和分析符号串集合的数学和计算机科学中的抽象概念。这些语言通常用于描述字符串的结构、语法和语义,以及在计算理论、编译原理、自动机理论等领域中进行形式化描述。
“自动机理论”是计算机科学中研究抽象计算设备和计算问题的理论分支之一。该理论涉及形式化描述和分析计算过程。自动机是一种数学模型,用于描述抽象的计算设备。它包括有限状态自动机(FiniteAutomaton)、推动自动机(PushdownAutomaton)、图灵机等。这些自动机模型有助于理解和分析计算问题的可解性。
“量子计算”是一种基于量子力学原理的计算模型,利用量子比特(Qubits)而不是经典比特进行信息存储和处理。量子计算的基本原理源于量子叠加和纠缠等现象,使得量子计算机具有在某些情况下远远超过传统计算机的计算能力的潜力。
以下是量子计算的一些关键概念:
数理逻辑是数学和哲学的交叉领域,研究形式系统和推理规则。它涉及了数学中的逻辑结构和命题关系,以及通过形式系统进行合理推理的原理。数理逻辑的应用涉及到计算机科学、哲学、语义学、数学基础等多个领域。它为理解和形式化推理提供了一种严密的框架,对于发展计算机科学和推理技术都具有重要意义。
【书籍】ModernMathematicalLogic
公理化集合论是一种将集合论的基础形式化为一组公理的方法。这种方法的目的是为集合论提供一个严格和无矛盾的理论基础。在数学的早期发展中,集合论是直觉上构建的,但这导致了一些悖论和问题,最著名的是罗素悖论。为了解决这些问题,数学家们提出了公理化集合论。
公理化集合论中,集合和它们的关系完全是由一系列公理所定义的。这些公理被设计为足够强大,以表达所有常见的集合论操作和结果,同时又足够严格,以避免悖论和不一致性。最著名的公理化集合论系统之一是策梅洛-弗兰克尔集合论(ZF),通常与选择公理(AC)一起使用,称为ZFC。
模型论是数理逻辑的一个分支,专注于研究形式语言(如数学中的逻辑语言)和它们的解释或“模型”之间的关系。在模型论中,一个“模型”是指一个数学结构(如群、环、图等),它用来解释一种形式语言中的语句和概念。这个领域探索不同的数学结构如何满足或不满足特定的逻辑语句或公理系统。
模型论的一个经典成就是哥德尔的不完备性定理,它表明在足够强的理论中(如包含基本算术的理论),存在不能被该理论证明或反驳的真实语句。模型论的工具和概念对于理解和处理这些深刻的数学和哲学问题至关重要。
通过这些公理,公理化集合论为现代数学提供了一个坚实和一致的基础,特别是对于无穷数学和数理逻辑领域。
证明论是数理逻辑的一个分支,专注于数学证明的形式和性质。证明论的核心目标是理解和分析数学证明的结构,以及通过形式化的方法来研究证明的过程和结果。证明论的研究有助于深化我们对数学推理本质的理解。
类型论是一种数学和计算机科学中的形式系统,用于研究和描述计算的性质。它起源于数理逻辑和哲学,目前在计算机科学、编程语言设计和数学基础等领域得到广泛应用。类型论的主要目标是通过引入类型来帮助避免程序错误,并提供一种严格的数学基础,以理解和证明计算过程。“类型”是关于值的分类。每个值都有一个关联的类型,而类型定义了值可以具有的性质和行为。通过强制类型,类型论有助于捕捉和防止一些常见的编程错误。类型论在程序验证领域中得到广泛应用。通过使用类型系统,可以在编译时捕获一些常见的编程错误,提高代码的可靠性。
范畴论(CategoryTheory)是数学中的一个抽象代数分支,研究各种数学结构和概念之间的普遍性质和关系。它以范畴为基本概念,通过研究范畴之间的映射(函子)和对象之间的映射(态射)来建立抽象的数学理论。以下是一些基本概念:
Haskell与范畴论有深刻的关系。范畴论中的概念,如函子、单子(monad)、自然变换等,直接影响了Haskell中的一些核心概念。
“程序验证”是一种使用数学和逻辑方法来确保计算机程序满足其规约和要求的过程。这一过程强调使用形式化方法,旨在验证程序在所有可能的输入条件下都能够产生正确的输出,并且不会出现错误或异常行为。这涉及到定义性质、编写证明、进行形式化推理等。
模型检查(ModelChecking)是计算机科学中的一种技术,用于自动化地验证有限状态系统(如硬件设计或计算机程序)是否满足给定的规范或属性。换句话说,模型检查是一种检查系统模型是否符合一组特定要求的方法。这种技术广泛用于软件和硬件的验证与调试,例如并发系统、通信协议、硬件设计等。
在模型检查中,系统的行为被建模为状态转换系统,其中系统的所有可能状态和状态之间的转换关系都被明确表示。性质通常以逻辑或时序逻辑的形式给出,例如是否存在某种状态序列满足某种性质。
自动化定理证明(简称ATP)是计算机科学和数理逻辑领域的一个重要分支,涉及开发计算机程序(称为定理证明器)来自动化地证明数学定理。这种技术的目标是减少或消除人工证明数学定理的需要,同时提供高度的准确性和效率。
【书籍】PrinciplesofProgramAnalysis[#豆瓣](PrinciplesofProgramAnalysis)
“形式化方法”是一种通过使用数学和形式化语言来进行系统设计、规约、验证和验证的软件和系统工程方法。这些方法旨在提高系统的可靠性、安全性和正确性,并在设计和开发的不同阶段中使用形式规约来明确定义系统的行为。
“Lambda演算”是一种数学形式化方法,用于描述计算和函数抽象。它是一种极简抽象模型,由数学家阿隆佐·邱奇(AlonzoChurch)于1930年代提出。Lambda演算对于计算理论的发展和理解函数式编程语言的基础具有重要影响。
Lambda演算的核心概念是函数抽象和应用。它使用一个简单的符号λ(lambda)来表示函数的定义,以及一个点(.)来分隔参数和函数体。Lambda演算的基本语法如下:
Lambda演算的一个关键特征是匿名函数(anonymousfunctions)。函数没有名称,而是通过参数和函数体来定义。Lambda演算是图灵完备的,这意味着它能够表示任何可计算的函数。Lambda演算在计算理论、编程语言设计和函数式编程方面有广泛的应用。它为理解函数式编程语言(如Lisp、Haskell、Scheme)的基本概念提供了理论基础。Lambda演算还在形式语言、编译原理和计算复杂性等领域中有重要的应用。Lambda演算的形式化定义允许研究计算过程的本质,而不涉及具体的计算机结构。这种抽象性使得Lambda演算成为理论计算机科学和计算理论的关键工具。
“图论”是数学的一个分支,研究图(Graph)的结构、性质和相互关系。图是由节点(顶点)和连接这些节点的边组成的数学模型,它是描述事物之间关系的一种抽象工具。
“布尔代数”是一种代数结构,它在逻辑和计算中具有重要的应用。它基于两个逻辑值(真和假),通常用0和1表示,以及逻辑运算(与、或、非)。
布尔代数在计算机科学、电子工程、逻辑设计等领域中被广泛应用。它为逻辑电路的设计和分析提供了理论基础,同时也是计算机程序设计中条件语句和逻辑运算的基础。
布尔函数是一类特殊的数学函数,其定义域和值域都是布尔集合({0,1})。这类函数在计算机科学、电子工程和逻辑设计等领域中具有重要的应用。一个布尔函数可以表示为将布尔值映射到另一个布尔值的规则。在布尔函数中,常见的逻辑运算包括AND、OR、NOT等,而布尔代数被广泛用于描述和分析这些函数。
在计算机科学中,布尔函数被应用在编码理论、数据结构和算法设计等方面。
“决策过程”是一种算法或系统,用于判断某个逻辑理论中的公式是否为可满足的(Satisfiable)或成立的(Valid)。这样的算法通常被设计用来解决特定逻辑理论中的问题,并且在给定输入的情况下,能够准确、自动地确定公式的真假。
如果你是一个自学成才的工程师,或者从编程培训班毕业,那么你很有必要学习计算机科学。幸运的是,不必为此花上数年光阴和不菲费用去攻读一个学位:仅仅依靠自己,你就可以获得世界一流水平的教育。
互联网上,到处都有许多的学习资源,然而精华与糟粕并存。你所需要的,不是一个诸如「200+免费在线课程」的清单,而是以下问题的答案:
在这份指引中,我们尝试对这些问题做出确定的回答。
大致按照列出的顺序,借助我们所建议的教材或者视频课程(但是最好二者兼用),学习如下的九门科目。目标是先花100到200个小时学习完每一个科目,然后在你职业生涯中,不时温习其中的精髓。
软件工程师分为两种:一种充分理解了计算机科学,从而有能力应对充满挑战的创造性工作;另一种仅仅凭着对一些高级工具的熟悉而勉强应付。
全球短信系统每日收发约200亿条信息,而仅仅靠57名工程师,现在的WhatsApp每日收发420亿条。
第一种工程师总是寻求深入学习计算机科学的方法,或是通过传统的方法学习,或是在职业生涯中永无止息地学习;第二种工程师通常浮于表面,只学习某些特定的工具和技术,而不研究其底层的基本原理,仅仅在技术潮流的风向改变时学习新的技能。
如今,涌入计算机行业的人数激增,然而计算机专业的毕业生数量基本上未曾改变。第二种工程师的供过于求正在开始减少他们的工作机会,使他们无法涉足行业内更加有意义的工作。对你而言,不论正在努力成为第一种工程师,还是只想让自己的职业生涯更加安全,学习计算机科学是唯一可靠的途径。
大多数计算机专业本科教学以程序设计「导论」作为开始。这类课程的最佳版本不仅能满足初学者的需要,还适用于那些在初学编程阶段遗漏了某些有益的概念和程序设计模式的人。
中文翻译新增:
为什么这么说呢?因为SICP是独一无二的,它可以——至少很有可能——改变你对计算机和编程的基本认识。不是每个人都有这样的体验。有的人讨厌这本书,有的人看了前几页就放弃了。但潜在的回报让它值得一读。
新版原文删除了对Concepts,Techniques,andModelsofComputerProgramming一书的推荐,但这本书对各种编程模型有深入的见解,值得一读。所以译文中依然保留。—译者注
计算机系统结构——有时候又被称为「计算机系统」或者「计算机组成」——是了解软件底层的的重要视角。根据我们的经验,这是自学的软件工程师最容易忽视的领域。
我们喜爱《深入理解计算机系统》,因为它的实用性,并且站在程序员的视角。虽然计算机体系结构的内容比本书所涉及的内容多得多,但对于那些想了解计算机系统以求编写更快、更高效、更可靠的软件的人来说,这本书是很好的起点。
我们推荐把此书的前六章读完,并完成对应的项目练习。这么做,你将更加深入地理解,计算机体系结构和运行其上的软件之间的关系。
为了追求简洁和紧凑,这本书牺牲了内容上的深度。尤其值得注意的是,流水线和存储层次结构是现代计算机体系结构中极其重要的两个概念,然而这本书对此几乎毫无涉及。
硬件是平台。
正如几十年来的共识,我们认为,计算机科学教育所赋予人们的最大能量在于对常见算法和数据结构的熟悉。此外,这也可以训练一个人对于各种问题的解决能力,有助于其他领域的学习。
我可以广泛推荐的方法只有一个:写之前先思考。
—RichardHamming
从某个角度说,计算机科学是应用数学的一个「发育过度」的分支。尽管许多软件工程师试图——并且在不同程度上成功做到——忽视这一点,我们鼓励你用学习来拥抱数学。如若成功,比起那些没有掌握数学的人,你将获得巨大的竞争优势。
如果人们不相信数学是简单的,那么只能是因为他们没有意识到生活有多么复杂。
—JohnvonNeumann
鉴于有那么多关于网络服务端和客户端的软件工程,计算机网络是计算机科学中价值最为「立竿见影」的领域之一。我们的学生,系统性地学习了计算机网络,最终能够理解那些曾困扰他们多年的术语、概念和协议。
你无法盯着水晶球预见未来,未来的互联网何去何从取决于社会。
—BobKahn
比起其他主题,自学数据库系统需要更多的付出。这是一个相对年轻的研究领域,并且出于很强的商业动机,研究者把想法藏在紧闭的门后。此外,许多原本有潜力写出优秀教材的作者反而选择了加入或创立公司。
如果没有编写足够数量的代码,很难巩固数据库理论。CS186课程的学生给Spark添加特性,倒是不错的项目,不过我们仅仅建议从零实现一个简单的关系型数据库管理系统。自然,它将不会有太多的特性,但是即便只实现典型的关系型数据库管理系统每个方面最基础的功能,也是相当有启发的。
不要做一个只写样板代码的程序员。相反,给用户和其他程序员创造工具。从纺织工业和钢铁工业中学习历史教训:你想制造机器和工具,还是操作这些机器?
—RasBodik在他的编译器课程伊始
随着计算机在数量上的增加,计算机同样开始分散。尽管商业公司过去愿意购买越来越大的大型机,现在的典型情况是,甚至很小的应用程序都同时在多台机器上运行。思考这样做的利弊权衡,即是分布式系统的研究所在,也是越来越重要的一项技能。
我们试图把计算机科学主题清单限制到那些我们认为每一个软件工程师都应该了解的内容,不限于专业或行业。拥有了这些基础,你将能更加轻松地挑选教材或论文,然而无需指引地学习核心概念。在这里,我们给出一些其他常见主题的自学起点:
事实上,所有主题之间都有一定程度的重叠,彼此循环引用。以离散数学和算法的关系为例:先学习数学可以帮助你更深入地分析和理解算法,然而先学习算法可以为学习离散数学提供更大的动力和应用背景。理想情况下,你将在你的职业生涯多次重温二者。
因此,我们所推荐的次序主要是为了帮助你起步……如果你出于某种强烈的原因而倾向以不同的顺序学习,那也没有关系,勇敢开始吧!不过在我们看来,最重要的「先决条件」是:先学计算机体系结构再学操作系统或数据库,先学计算机网络和操作系统再学分布式系统。
没有任何一种技术的重要程度可以达到学习其使用足以成为计算机科学教学的核心部分。不过,你对学习那门技术充满热情,这很不错。诀窍是先从特定的技术回退到基本的领域或概念,判断这门流行技术在技术的宏观大局中位于何处,然后才深入学习这门技术。
先尝试读一下,有些人觉得SICP让人神魂颠倒,这在其他书很少见。如果你不喜欢,你可以尝试其他的东西,也许以后再回到SICP。
龙书依旧是内容最为完整的编译器单本书籍。由于过分强调一些如今不够时新的主题的细节,比如解析,这本书招致了恶评。然而事实上,这本书从未打算供人一页一页的学习,而仅仅是为了给教师准备一门课程提供足够的材料。类似地,自学者可以从书中量身按需挑选主题,或者最好依照公开课授课教师在课程大纲中的建议。
我们所建议的许多教材在网上都可以免费获得,这多亏了作者们的慷慨。对于那些不免费的书籍,我们建议购买旧版本的二手书籍。广而言之,如果一本教材有多个版本,旧版本大概率是完全足够使用的。即便新版本的价格是旧版本的10倍,新版本也绝不可能比旧版本好10倍!
为什么每个人都匆匆忙忙?
走进任何一个书店,你都能看到《24小时学会Java》这样的书,旁边还会有各种变种,教你怎么在几个小时或者几天内学会C、SQL、Ruby、算法等等。
用亚马逊的高级搜索[标题:teach,yourself,hours,since:2000]可以找到512本这样的书,其中排名前10的有9本都是编程的书籍(另外一本是关于记账的)。你用learn替代teachyourself,或者用days替代hours可以得到相同的结果。
这么看来,要么就是人们学习编程非常地匆忙,要么就是编程学起来比其他东西简单多了。Felleisen等人在他们《如何设计程序》一书中承认了这个潮流。他们说:“坏的编程是容易的,就算是白痴也能在21天里面学会坏编程。”
AbstruseGoose网站也有一个这样的漫画来讽刺这种现象。
我们来分析一下,一个像《24小时内教会你自己C++》这样的标题意味着什么:
关键在于刻意的练习:不仅仅是一遍又一遍的重复,而是用正好超出你能力边界一点点的任务挑战自己。尝试,并在过程中和之后分析自己的表现,并纠正任何错误。然后就是重复,再重复。
看起来并没有一个明显的捷径:即便是4岁就已经是音乐神童的莫扎特,也要等到13年之后才开始创作出世界级的音乐。Beatles乐队看起来像是从1964年的一场演唱会开始突然火起来,但是他们从1957年开始就在利物浦和汉堡的小酒吧里面表演了,而直到1967年他们才创作出第一个真正的伟大关键作品,虽然在那之前他们已经挺火的了。
所以你想成为一个程序员这里是我的编程成功秘诀:
所以,可以继续,买下那本Java/Ruby/Javascript/PHP的书;你很可能会发现还是有点用处。但是它不能在24小时或者21天内改变你的生命,或者你的真正编程技巧。继续坚持持续提升24个月呢?很好,你现在正开始向某个地方前进了……