编程c语言要数学很好吗,编程与数学的关系:学好编程就能学好数学吗?
原标题:编程与数学的关系:学好编程就能学好数学吗?
在大学数学学科中
线性代数是最为抽象的一门课
从初等数学到线性代数
思维跨度比微积分和概率统计要大得多
大多数小伙伴学过以后一直停留在
知其然不知其所以然的阶段
若干年之后接触图形编等领域
才发现线性代数的应用无处不在
但又苦于不能很好地理解和掌握
多数人很容易理解初等数学的各种概念

函数、方程、数列
一切都那么的自然
但是一进入线性代数的世界
就好像来到了另一个陌生的世界
在各种奇怪的符号和运算里迷失了

在初接触线性代数的时候
简直感觉这是一门天外飞仙的学科
一个疑问在脑子里浮现出来
线性代数到底是一种客观的自然规律还是人为的设计?
如果看到这个问题
小伙伴的反应是
“这还用问,数学当然是客观的自然规律了”
一点儿都不觉得奇怪
我也曾这样认为
从中学的初等数学和初等物理一路走来
很少人去怀疑一门数学学科是不是自然规律
当学习微积分、概率统计时
也从来没有怀疑过
唯独线性代数让我产生了怀疑
因为它的各种符号和运算规则太抽象 太奇怪
完全对应不到生活经验
线性代数
引发了我去思考一门数学学科的本质
其实
不止是学生
包括很多数学老师
都不清楚线性代数到底是什么 有什么用
不仅国内如此
国外也是这样
国内的孟岩写过《理解矩阵》
国外的Sheldon Axler教授写过《线性代数应该这样学》
都没有从根本上讲清楚线性代数的来龙去脉
对于我自己来讲
读大学的时候没有学懂线性代数
反而是后来从编程的角度理解了它
很多人说数学好可以帮助编程
我恰好反过来了
对程序的理解帮助了我理解数学
下面老九君就带小伙伴们
做一次程序员在线性代数世界的深度历险!
既然是程序员
在进入线性代数的领域之前
我们先考察一番程序世界
请思考这样一个问题:
计算机有
汇编、C/C++、Java、Python等通用语言
还有Makefile、CSS、SQL等DSL
这些语言是一种客观的自然规律还是人为的设计呢?
为什么要问这样一个看起来很蠢的问题呢?
它的答案显而易见
对天天使用的程序语言的认识
一定胜过抽象的线性代数
程序语言虽然包含了内在的逻辑,
但它们本质上都是人为的设计
所有程序语言的共同性在于
建立了一套模型
定义了一套语法
将每种语法映射到特定的语义
程序员和语言实现者之间遵守语言契约
程序员保证代码符合语言的语法
编译器/解释器保证代码执行的结果
符合语法相应的语义
比如
C++规定用new A()语法在堆上构造对象A
这样写了C++就必须保证相应的执行效果
在堆上分配内存并调用A的构造函数
否则就是编译器违背语言契约
从应用的角度,我们能不能把线性代数视为一门程序语言呢?
答案是肯定的,我们可以用语言契约作为标准来试试。
假设有一个图像,我们想把它旋转60度,再沿x轴方向拉伸2倍;
线性代数告诉我们,“诸位!请按照我的语法规范构建这个变换矩阵,并将这个变换应用到你们提供的图像上;按照矩阵乘法规则完成这一操作后,请期待最终输出的结果完全符合你们的需求。”
实际上,线性代数和SQL这样的DSL非常相似,下面来作一些类比:
模型与语义:基于低级语言之上构建了关系型数据库模型,在该框架中涉及的核心概念包括关系及其运算;而线性代数则以初等数学为基础发展出了向量空间理论,在这一领域中其核心概念包括向量空间及其变换
SQL语言为表示各种语义而设计了一套完整的语法结构;除了上述之外,在线性代数领域还涉及向量、矩阵以及它们之间的乘法运算等基本概念,并基于这些概念构建了一套相关的语法系统
编译/解码:SQL可以通过多种方式被解析为C语言代码;线性代数相关概念与运算规范可以通过基本的数学原理与方法论来阐述这些理论基础及其操作流程
支持在MySQL和Oracle等关系型数据库中执行SQL指令;另外一种情况是,在MATLAB和Mathematica等数学软件中进行线性代数运算
从应用角度来看,线性代数可被视为一套人工构建的领域特定语言(DSL),它通过符号系统实现了语法结构和语义规则的完整映射。
确实,在数学中向量、矩阵及其运算规则所具有的语法和语义结构本质上是由人类所定义的。这些数学对象及其语法、语义结构与一种语言系统中的各种概念性质相平行,并且这种体系本质上是一种构建。但前提条件则是必须遵循语言契约。
为什么要有线性代数?
有些人可能对将线性代数视为一门Domain-Specific Language(DSL)的方法表示怀疑,在这种情况下,请提供一个矩阵,则会对我的图形执行60度的旋转操作,并在x轴方向上放大两倍。我对这种处理方式仍感到不安,因为我不清楚您使用的具体实现细节是什么。
实际上, 这就如同有些程序员对高级编程语言不太安心, 认为底层才是程序的本质, 总是忍不住好奇将这段代码编译成汇编会是什么样子? 这个操作又占用了多少内存? 其他人只需要在Shell中输入简单的wget命令就能快速获取网页内容, 为何非要学习C语言编写冗长耗时的代码才感到安心呢?
所谓底层和上层只是一种习惯性的说法,并不是谁比谁更本质。
从语义层面来看,程序的编译与解释实质上构成了不同计算模型之间的映射关系.在常规情况下,则是将高级编程语言映射至底层编程语言.然而,并非只能如此;完全有可能将这种方向逆转过来.法国计算机科学家Fabrice Bellard开发了一个基于JavaScript的虚拟机平台,在此平台上实现了Linux操作系统运行功能.
任何新模型的构建都离不开现有模型的支持;然而其作用仅限于提供解决问题的方法而非目标本身;每一个新建立的模型最终都将致力于以更为简洁的方式分析并解决特定类型的问题
在线性代数建立的过程中, 它们所涉及的各种概念与运算规则都是以初等数学知识为基础构建起来的. 当构建起这一层抽象模型后, 我们应当习惯地运用更高层次的抽象框架来进行问题分析与解决.
线性代数旨在使得分析和解决问题更加简便地应用于各个领域。通过一个具体的例子来体会它的便利之处。
给定三角形的顶点(x1, y1), (x2, y2), (x3, y3),求三角形的面积:
初等数学中三角形面积最著名的计算公式是area = 1/2 * base * height
当三角形有一条边恰好在坐标轴上时我们就很容易算出它的面积。
然而,在将同一个三角形置于旋转后的坐标系中(即其边不再位于原来的x或y轴上),我们是否仍然能够确定该三角形的底与高?
该问题的答案毫无疑问是可行的,然而实际上却相当复杂。这意味着在分析时需要考虑多种不同的情况。
相反,如果我们用线性代数知识来解决这个问题就非常轻松。
在现代线性代数领域中研究的是两个向量a和b之间的运算关系。其中一种重要的运算称为向量积(或叉乘),其结果是一个与原向量都垂直的新向量。该运算的结果矢量的方向垂直于原始平面,并遵循右手法则。其模长等于由这两个矢量所张成的平行四边形的面积。
我们可将三角形的边视为向量,并由此可知三角形的面积等于两个相关边向量叉积所得向量长度的一半:
area = 1/2 * length(cross_product((x2 - x1, y2 - y1), (x3 - x1, y3 - y1)))
注:length表示取向量长度,cross_product表示两个向量的叉积。
这样一个在初等数学里面有点儿小难的问题在线性代数中瞬间搞定!
有些人可能会认为直接基于叉积进行计算确实是一个简单的方法。然而实际上,并非如此——因为虽然这种方法看似简便直观但其内在的复杂性并未被表面现象所掩盖——即尽管这种方法看似简便直观但其内在的复杂性并未被表面现象所掩盖——即虽然这种方法看似简便直观但其内在的复杂性并未被表面现象所掩盖并行处理并行处理并行处理并行处理并行处理并行处理并行处理并行处理
是的, 模型承担着将部分复杂性封装起来的任务, 并帮助用户更方便地解决问题. 有些人曾对C++过于复杂的批评. 回答道:
Complexity will be resolved: unless the language is at fault, the application code is to blame.
在特定环境下, 问题的复杂程度是由其内在特性所决定, C++通过整合部分技术细节到语言体系及标准库中, 以期使程序开发更加便捷.
然而,在某些情况下,并非所有场合使用C++都能使问题变得更为简单;但从本质上说,C++的复杂性是合理的。
不光只有C++在编程中占据重要地位,在其他编程语言与框架中也有着相似的现象。想想看,在没有数据库的情况下(即必须自行处理数据存储与管理),这会有多复杂?
In linear algebra, it is not immediately obvious why the cross product is defined in such an unconventional manner, as it parallels C++'s approach of incorporating a vast array of commonly used algorithms and data structures into its standard template library (STL) by employing a similar methodology.
同样的,甚至小伙伴还可以在线性代数中定义自己想要的运算拿来复用。
所以, 数学并非枯燥无味, 它就像程序一样充满活力, 了解其发展脉络后便能得心应手地运用. 这里我们顺便解答一个常见的疑问:
线性代数中的内积、外积以及矩阵运算都令人感到困惑,它们的设计背后是否隐藏着某种合理的逻辑基础呢?为何会采用这样的结构呢?
其实在程序复用的基础上类似地在线性代数中定义点积叉积以及矩阵运算的目的在于它们有着广泛的应用并且具有显著的复用价值这些运算构成了分析与解决问题的基础工具
例如,在许多问题中都会遇到将一个向量投射至另一个向量的方向上或是计算两个向量之间的角度的情形;这样一来,则会考虑专门定义点积(Dot Product)这一运算:

点积概念的阐述归于设计范畴,并留有发挥创造的空间;当设计确定后,则其具体公式就无法任意更改,并需遵循逻辑规律以确保其映射至基础数学模型时的一致性和准确性。
这类似于一种高级编程语言包含诸多概念如高级函数和闭包等 但它们必须确保将这些概念映射到底层实现时 在执行过程中所产生的效果符合它们所定义的规范
线性代数好在哪里?
上面提到了一点关于线性代数的知识。可以说它属于一种高级抽象体系。我们都可以通过学习编程语言的学习方法来掌握它的语法和语义结构。然而这种观点不仅限于线性代数它还适用于所有其他数学学科也许会对此提出质疑
微积分与概率论同样属于高度抽象领域,则线性代数在这一层次的抽象性体现在哪里呢?
这就问到了根本上,线性代数的核心:向量模型。
在初等数学教育中教授的坐标系归功于笛卡尔提出的解析模型。这一模型非常有效,在解决许多几何问题时表现出色,然而它也存在明显的缺陷。
坐标系是一个人为构造出来的虚拟参考系统。然而,在我们实际需要解决的问题中(如计算面积),以及图形旋转和拉伸等应用场景中都与之无涉。建立这样一个虚设的坐标系统通常会没有帮助。就像前面举的例子那样。
向量型知识体系在某种程度上超越了解析型知识体系所面临的局限性。从另一个角度来看,在这种观点下(绝对主义),解析型的知识体系显得有些过于僵化;而相比之下,在这种观点下(相对主义),向量型的知识体系则更具灵活性。因此,在我的看法中,将这两种知识体系视为根本对立的观点是值得商榷的。
在向量模型中对向量与标量的概念进行了定义。在数学空间中,默认地将该空间中的元素划分为两类:一类是既有大小又有方向特性的量化对象——即向量子类;另一类仅具备大小属性而无方向特异性——即标量子类。具体而言,在旋转变换过程中其数值保持不变的量化指标即为一种典型的标量子类特征描述。
向量模型的一个显著优势在于其不受坐标系影响的特点,在定义向量及其运算规则时就刻意避免了任何与坐标系相关联的因素,在这种设计下无论坐标轴如何旋转我对这种适应状态感到自然的各种如线性组合内积叉积以及线性变换等运算都完全不受坐标系的影响
需要注意的是,并非没有使用到坐标的场景存在。事实上,在之前的三角形例子中顶点的位置确实是以具体坐标的形式给出的。然而,在解决问题的过程中不同坐标的选取并不会产生显著的影响。
Java自称平台独立,并非表示它是无 foundation 的空中建筑;实际上开发者在使用 Java 编程时所依赖的操作系统是 Linux 还是 Windows 对他们自身并无影响。
向量模型有什么好处呢?
除了刚才三角形面积问题是一个例子,下面再举一个几何的例子:
已知在三维坐标系中的任意一点(x₀, y₀, z₀)和一个平面方程ax + by + c*z + d = 0,请问此点到该平面的垂直距离如何计算?

若采用解析几何的方法几乎难以入手,则必须依赖特殊情况;而采用向量模型则非常简便:
由平面方程可知,平面的法矢量N=(a,b,c),取平面上任一点P(x,y,z),考虑该点与目标点P₀(x₀,y₀,z₀)之间的向量w=P-P₀。首先计算向量w与法矢量N的点积得到投影长度。其次将该长度作为目标点P₀到平面ax+by+cz+d=0的距离。即为该空间中任一点P(x₀,y₀,z₀)至平面ax+by+cz+d=0的最短距离。
在本研究中涉及了向量模型的核心要素:法线向量、投影矢量以及点乘积;整体解决方案呈现出清晰简洁的特点。
再次为小伙伴们提供一道类似的练习题(那些熟悉机器学习的朋友可能认识到这是线性代数在线性分类中的应用):
设为P(a₁,a₂,…,aₙ)和Q(b₁,b₂,…,bₙ),以及一个超平面c₁x₁ + c₂x₂ … + cₙxₙ + d = 0,请确定这两点位于该超平面的同一侧还是异侧?
离开向量,下面我们要请出线性代数的另一个主角:矩阵(Matrix)。
线性代学涵盖了矩阵与向量以及矩阵间的乘法运算。这些运算规则颇具挑战性,在实际应用中尚不明确。对于许多新手而言,在学习过程中常常感到困惑不解。就当前学习现状而言,这一概念确实给许多学生造成了障碍。
遇到复杂的东西,往往需要先避免一头陷入细节,先从整体上把握它。
从本质上说,在程序设计中。不管形式如何复杂,任何一种编程范式都无非是一种语法结构。这种语法结构必然与相应的语义关联着。因此掌握矩阵的核心内容对于解析语言至关重要。
矩阵的语义多种多样,在不同的情境下呈现出各自独特的意义,在同一环境中也可能存在多种解读的可能性。其中最常见的有:
1)表示一个线性变换;
2)表示列向量或行向量的集合;
3)表示子矩阵的集合。
矩阵整体上相当于线性变换语义:通过矩阵A作用于向量v得到结果w,则矩阵A即代表了从v到w的线性变换过程。
例如,若希望将向量v₀沿counterclockwise方向旋转60度以获得结果向量v',则只需将旋转变换矩阵作用于v₀即可完成操作

除了旋转变换之外,在仿射变换家族中还有一种重要的线性变换——缩放变换。例如,在实际应用中(如计算机图形学),我们可以使用一个缩放矩阵将向量沿着x轴放大或缩小特定倍数(试着推导出缩放矩阵的具体形式)。
更重要的一点是,在矩阵乘法中存在一个显著的优势:其运算结果满足结合律;这表明线性变换能够叠加起来。
举例而言,在进行线性代数运算时
这是不是很像我们Shell中把多个命令通过管道进行叠加呢?
上面重点阐述了向量模型的坐标系无关特性,并且这一特性也体现了其不受坐标系影响的特点;此外而言,在描述线性关系方面它同样展现出显著的优势;下面让我们来探讨一下著名的斐波那契数列实例:
该数列的递推关系式为f(n) = f(n-1) + f(n-2), 其初始条件是f(0)=0和f(1)=1;任务是: 给定整数n, 请设计一个时间复杂度不超过\mathcal{O}(\log n)的算法来计算该Fibonacci数列的第n项。
首先,我们构造两个向量v1=(f(n+1), f(n))和v2=(f(n+2), f(n+1)),根据Fibonacci
数列性质,我们可以得到从v1到v2的递推变换矩阵:

并进一步得到:

这样就把线性递推问题被转化为了矩阵的n次幂的经典问题,并能够在O(log n)的时间复杂度下解决。此外,在初等数学中,n元一次方程组的问题同样能够通过矩阵与向量乘法的形式得到较为简便的解决方案。
这一实例旨在说明:所有符合线性关系系统的适用领域均为向量模型。通常而言,在处理这类问题时, 我们可以通过将其转换为线性代数形式来获得简洁而高效的解决方案。
总结
本文探讨了一种观点:在应用层面中将其视为一门特定领域的程序语言。在线性代数的基础上构建了向量模型,并详细阐述了其语法体系和语义规范。
向量模型具备坐标系无关性和线性性的特点,并在整体上构成了线性代数的核心内容。深入理解和掌握向量的概念及其相关属性和变化规律对于学习线性代数至关重要。
对于编程学习来说,掌握数学知识是关键基础.在线性代数的学习过程中,借助编程思维进行分析能够提高理解和应用能力.fopen speculate, more information.
责任编辑:
