例谈数学在计算机编程中的应用.docx
- 文档编号:4260785
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:12
- 大小:27.01KB
例谈数学在计算机编程中的应用.docx
《例谈数学在计算机编程中的应用.docx》由会员分享,可在线阅读,更多相关《例谈数学在计算机编程中的应用.docx(12页珍藏版)》请在冰豆网上搜索。
例谈数学在计算机编程中的应用
例谈数学在计算机编程中的应用
来源:
浙江省温州中学 作者:
舒春平 发布时间:
2006-11-18
【序言】
本人对计算机编程有着浓厚兴趣,在平时的信息学竞赛辅导教学中,深刻体会到了数学这一自然科学的“王后”,在计算机编程中的广泛应用。
本文将以六个实例与大家共同探讨。
【正文】
首先我们来看一个使用数学方法可以大大提高效率的例子。
实例一:
给定一个自然数a,判断它是不是质数。
普通的想法:
若a是合数,那么必然有一个因数不大于a1/2,建立一个a1/2以内的质数表,逐一检索。
显然,这样速度太慢!
下面介绍一种基于费马小定理的Miller-Rabin测试算法:
首先是引理:
费马小定理,相信大家都有耳闻,这里我也不嫌累赘,仍旧列出。
若n是质数,(a,n)=1,则an-1mod n =1。
同样,若我们选取若干个a,都满足以上等式的话,几乎可以肯定n是素数。
(尽管不能完全确认,但在实际操作中是可行的)
下面给出算法:
Function Miller-Rabin(n:
longint):
Boolean;
Begin
For I:
=1 to s do
Begin
a:
=random(n-2)+2;
If modular_exp(a,n-1,n)<>1 then return false;
End;
Return true;
End;
事实上,数学在计算机当中最为重要的还是递推关系的应用:
许多看似棘手的题目,在有了这一层的关系后便显得柳暗花明了。
实例二:
Hannoi塔问题
Hanoi塔由n个大小不同的圆盘和三根木柱a,b,c组成。
开始时,这n个圆盘由大到小依次套在a柱上,
要求把a柱上n个圆盘按下述规则移到c柱上:
(1) 一次只能移一个圆盘;
(2) 圆盘只能在三个柱上存放;
(3) 在移动过程中,不允许大盘压小盘。
问将这n个盘子从a柱移到c柱上,总计需要移动多少个盘次?
解:
设hn为n个盘子从a柱移到c柱所需移动的盘次。
显然,当n=1时,只需把a柱上的盘子直接移动到c柱就可以了,故h1=1。
当n=2时,先将a柱上面的小盘子移动到b
柱上去;然后将大盘子从a柱移到c柱;最后,将b柱上的小盘子移到c柱上,共计3个盘次,故h2=3。
以此类推,当a柱上有n(n>=2)个盘子时,总是先借助c柱把上面
的n-1个盘移动到b柱上,然后把a柱最下面的盘子移动到c柱上;再借助a柱把b柱上的n-1个盘子移动到c柱上;总共移动h(n-1)+1+h(n-1)个盘次。
所以:
hn=2h(n-
1)+1 (边界条件:
h1=1)
这个问题其实只是数学题目的简单变形。
下面再来看一个应用更加灵活的例子:
实例三:
方格取数
在一个n*m的方格中,m为奇数,放置有n*m个数,
方格中间的下方有一人,此人可按照正前方相临的五个方向(方格)前进但不能越出方格。
人每走过一个方格必须取此方格中的数。
要求找到一条从底到顶的路径,
使其数相加之和为最大。
输出和的最大值。
解:
这题在本质上类似于递推,是从一个点可以到达的点计算可以到达一个点的所有可能点,然后从中发掘它们的关系。
我们用坐标(x,y)唯一确定一个点,其中
(m,n)表示图的右上角,而人的出发点是([m/2],0),受人前进方向的限制,能直接到达点(x,y)的点只有(x+2,y-1),(x+1,y-1),(x,y-1),(x-1,y-1),(x-2,y-1)。
到达(x,y)的路径中和最大的路径必然要从到(x+2,y-1),(x+1,y-1),(x,y-1),(x-1,y-1),(x-2,y-1)的几条路径中产生,既然要求最优方案,当然要挑一条和最大的
路径,关系式如下:
F(x,y)=Max{F(x+2,y-1),F(x+1,y-1),F(x,y-1),F(x-1,y-1),F(x-2,y-1)}+Num(x,y),其中Num(x,y)表示(x,y)点上的数字。
(边界条件为:
F
([m/2],0)=0,F(x,0)=-0(1<=x<=m且x<>[m/2]))。
这种问题,涉及到最值,采用的递推手法被称为"动态规划"。
简称DP。
程序设计中可采用多种数学方法,恰如其分的数学方法可以大大减少程序运行的时间和所需空间,起到优化程序的作用。
遇到一道题目时,如进制运算,多项式运算
等,应不急于马上用递归,回溯等搜索算法,特别是测试数据的范围很大的时候。
不妨先用笔算,从中发现一些规律.但是也不是每一道题都可以用数学方法完成,数学
方法只能用于一些求总数,最值之类的题目上。
下面便是经典应用之一:
实例四:
砝码设计
设有一个天平,可以用来称重.
任务一:
设计n个砝码的重量,用他们能称出尽可能多的整数重量.例如,n=2,设计2个砝码的重量分别为1和3, 可称重为1,2,3,4的连续重量.
任务二:
在给出n个砝码能称出最大重量范围的一重量x,试给出称出x的方案.
在上例中:
给出x=2称出的方案为2+1:
3
x=4称出的方案为4:
1+3
x=1称出的方案为1:
1
输入:
n,x(n为砝码个数,x是在称出最大重量范围内的重量)
输出:
砝码方案,称出x的方案.
输入样例1:
2,2 输入样例2:
2,4
输出样例1:
1,3 输出样例2:
1,3
由题意可知此题不适合搜索。
由任务一可知:
n=2时砝码重量最优解为1、3。
我们可以试n=3,n=4...的情况,不难发现本题是一个“平衡三进制”的应用,砝码的重
量均为3的1至n次方,由于理论推导涉及到累加等数学知识,我们着重看任务二。
任务二要求输出用砝码称出重为x的重量,实际上就是用3的0至n-1次方的和差来表示x,如样例中的2=3-1,4=1+3等,不难发现,当x除以3余1时,必然x要表示为
x=a1+a2...+1,余2时x=a1+a2...-1,余0时不用1的砝码.因此取x除以3的余数,可以确定砝码1用不用和用在天平的哪一边.同理,判断3的砝码位置时,可先将x先除以3
四舍五入,再除以3取余判断.能用3的1至n次方的和差来表示x后,屏幕输出再用一个数组来处理就行了。
参考算法:
procedure balance (x:
integer);
var
j,b:
integer;
begin
t1:
=0; t2:
=0; j:
=1;
repeat
b:
=x mod 3;
x:
=round(x/3);
if b=2 then begin t1:
=t1+1; ch1[t1]:
=j; end; {物品一端}
if b=1 then begin t2:
=t2+1; ch2[t2]:
=j; end; {砝码一端}
j:
=j*3;
until x=0;
end;
接下来,让我们来看一个数学原理在图论中的应用:
实例五:
欧拉回路
首先让我们了解一个定义:
欧拉回路与欧拉图 包含了图G的每一条边,且每条边仅出现一次的通路,就是欧拉通路。
包含了图G的每一条边,且每条边仅出现一次的回路,就是欧拉回路。
存在欧拉回路的图,称为欧拉图。
存在欧拉通路,但不存在欧拉回路的图,称为半欧拉图。
欧拉回路要求边不能重复,结点可以重复。
笔不离开纸,不重复地走完所有的边,回到原处。
就是所谓的一笔画。
怎样判定一个图是不是欧拉图呢,我们有以下方法:
欧拉图的判定:
(1) 无向连通图G是欧拉图?
G不含奇数度的结点(即G的所有结点的度均为偶数(0视为偶数));(定理1)
(2) 非0平凡图G有欧拉通路?
G最多有两个奇数度的结点;(定理1的推论)
(3) 有向图D是欧拉图?
D连通且D的所有结点的入度等于出度。
有向连通图有欧拉通路?
除两个结点外,其余结点的出度均等于入度,且这两点deg-(v)-deg+(v)=±1。
(定理2)
来看一个实际应用的题目:
农民John每年有很多栅栏要修理。
他总是骑着马穿过每一个栅栏并修复它破损的地方。
John是一个与其他农民一样懒的人。
他讨厌骑马,因此从来不两次经过一个一个栅栏。
你必须编一个程序,读入栅栏网络的描述,并计算出一条修栅栏的路径,使
每个栅栏都恰好被经过一次。
John能从任何一个顶点(即两个栅栏的交点)开始骑马,在任意一个顶点结束。
每一个栅栏连接两个顶点,顶点用1到500标号(虽然有的农场并没有500个顶点)。
一个顶点上可连接任意多(>=1)个栅栏。
所有栅栏都是连通的(也就是你可以从任意
一个栅栏到达另外的所有栅栏)。
你的程序必须输出骑马的路径(用路上依次经过的顶点号码表示)。
输入数据保证至少有一个解。
这便是一个典型的欧拉回路问题,每一个栅栏都是一条边。
根据上文的阐述,我们有以下算法:
任取一个起点(若有两个奇数度的点,则从其中一点开始),开始下面的步骤
如果该点没有相连的点,就将该点加进路径中然后返回。
如果该点有相连的点,就列一张相连点的表然后遍历它们直到该点没有相连的点。
(遍历一个点,删除一个点)
处理当前的点,删除和这个点相连的边,在它相邻的点上重复上面的步骤,把当前这个点加入路径中。
参考程序:
var
net:
array[1..500,1..500] of boolean; {存储网络图}
path:
array[1..500,1..500] of integer; {记两个顶点有多少条路径,不一定只有一条}
du:
array[1..500] of integer; {记每个顶点的度}
queen,stack:
array[1..10000] of integer; {堆栈和队列}
i,k,len,r,max,m,n,f,q:
integer;
flag:
boolean;
begin
fillchar(net,sizeof(net),false);
fillchar(du,sizeof(du),0);
fillchar(path,sizeof(path),0);
readln(f);
max:
=0; {记录出现的最大结点编号}
for i:
=1 to f do
begin
readln(n,m);
inc(du[n]); inc(du[m]);
if max
if max
net[n,m]:
=true; net[m,n]:
=true;
inc(path[n,m]); inc(path[m,n]);
end;
{---------------------- main ------------------}
q:
=1;
len:
=0;
for i:
=1 to max do
if du[i] mod 2=1 then begin q:
=i; break; end; {找奇度点}
k:
=q;
repeat
flag:
=true;
for i:
=1 to max do {找遍与k点相连的所有边}
if net[k,i] then
begin
if path[i,k]>1 then begin path[i,k]:
=path[i,k]-1; path[k,i]:
=path[k,i]-1; end
else begin net[k,i]:
=false; net[i,k]:
=false; end;
r:
=r+1; stack[r]:
=k; k:
=i; flag:
=false; break;
end;
if flag then begin inc(len); queen[len]:
=k; k:
=stack[r]; r:
=r-1; end; {出栈}
until r<0;
for i:
=len downto 1 do writeln(queen[i]); {输出欧拉路}
end.
在计算机编程中,组合数学的应用也非常广泛,最后,让我们看一个组合数学在编程中的实际例子:
实例六:
无聊的排序
你弟弟有一项家庭作业需要你帮助完成。
老师给了他一列数,需要他把这些数按升序排列。
你可以每次交换两个数的位置,而一次交换的代价被定义成被交换的两个
数的和。
写一个程序,用最小的交换代价和来帮助弟弟完成这项无聊的排序工作。
输入:
第一行为一个数N(N<=100),第二行为互不相同的N个数。
输出:
输出一个数,为最小的交换代价和
解:
本题可以抽象为把一列数从初始状态变成目标状态,即完成一个置换。
根据群论知识,置换可以分解为s个不相交的循环的乘积。
显然,由于每次只有被交换两
个数的位置改变,所以要想改变一个数的位置,只能通过交换完成,而不能像插入排序一样,可以借助其他数来完成,即各个循环是相互独立的,所以应该依次完
成每个循环。
为了得到尽量少的交换代价,在每个循环中较好的方法是让循环中最小元素或全局最小元素参加所有的交换。
至于用循环内的最小元素还是用全局中
的最小元素,就要比较哪个交换代价更小了。
参考程序:
var
a,b:
array[1..100] of integer;
n,i,inum,num,numtmp,len,j,k:
integer;
sum:
longint;
begin
readln(n); num:
=maxint;
while n<>0 do
begin
for i:
=1 to n do read(a[i]); {读入信息存放a中}
readln;
b:
=a;
for i:
=1 to n-1 do {选择排序b数组}
begin
k:
=i;
for j:
=i+1 to n do
if b[j]
if k<>i then begin numtmp:
=b[k]; b[k]:
=b[i]; b[i]:
=numtmp; end;
end;
num:
=b[1];
sum:
=0;
for i:
=1 to n do
if a[i]<>-1 then {分别处理每个循环节}
begin
inum:
=b[i]; numtmp:
=a[i]; len:
=0;
while inum<>a[i] do
begin
for k:
=1 to n do
if a[k]=inum then break;
if inum
sum:
=sum+inum;
inum:
=b[k];
a[k]:
=-1;
inc(len);
end;
sum:
=sum+inum; inc(len); a[i]:
=-1;
if (len-2)*numtmp
sum:
=sum+ (len-2)*numtmp
else
sum:
=sum+ numtmp+(len+1)*num;
end;
writeln(sum);
readln(n);
end;
end.
【结束语】
数学方法的合理运用,可以给编程带来很大方便,现在一些省市的信息学竞赛题,越来越多的用到数学推导归纳。
在竞赛中要取得好成绩,坚实的数学基础和能力是很重要的。
不仅是在编程方面,在计算机的其他领域中,数学也有广泛的应用。
但限于时间与水平的关系。
本文只探讨至此,愿它对大家能够有所帮助。
数学在计算机图形学中的应用
数学在计算机图形学中的应用
数学在计算机图形学中的应用
Greg Turk, August 1997
“学习计算机图形学需要多少的数学?
”这是初学者最经常问的问题。
答案取决于你想在计算机图形学领域钻研多深。
如果仅仅使用周围唾手可得的图形软件,你不需要知道多少数学知识。
如果想学习计算机图形学的入门知识,我建议你读一读下面所写的前两章(代数,三角学和线性代数)。
如果想成为一名图形学的研究者,那么对数学的学习将是活到老,学到老。
如果你并不特别喜欢数学,是否仍有在计算机图形学领域工作的机会?
是的,计算机图形学的确有一些方面不需要考虑太多的数学问题。
你不应该因为数学成绩不好而放弃它。
不过,如果学习了更多的数学知识,似乎你将在研究课题上有更多的选择余地。
对于在计算机图形学中哪些数学才是重要的还没有明确的答案。
这领域里不同的方面要求掌握不同的数学知识,也许兴趣将会决定了你的方向。
以下介绍我认为对于计算机图形学有用的数学。
别以为想成为一名图形学的研究者就必须精通各门数学!
为了对用于图形学的数学有一个全面的看法,我特地列出了很多方面。
但是许多研究者从不需要考虑下面提到的数学。
最后,虽然读了这篇文章后,你应该会对数学在计算机图形学中的应用有所了解,不过这些观点完全是我自己的。
也许你应该阅读更多的此类文章,或者至少从其他从事计算机图形学工作的人那里了解不同的学习重点。
现在开始切入正题。
代数和三角学
对于计算机图形学的初学者来说,高中的代数和三角学可能是最重要的数学。
日复一日,我从简单的方程解出一个或更多的根。
我时常还要解决类似求一些几何图形边长的简单三角学问题。
代数和三角学是计算机图形学的最基础的知识。
那么高中的几何学怎么样呢?
可能让人惊讶,不过在多数计算机图形学里,高中的几何学并不经常被用到。
原因是许多学校教的几何学实际上是如何建立数学证明的课程。
虽然证明题对提高智力显然是有效的,但对于计算机图形学来说,那些与几何课有关的定理和证明并不常被用到。
如果你毕业于数学相关领域(包括计算机图形学),就会发现虽然你在证明定理,不过这对开始学习图形学不是必要的。
如果精通代数和三角学,就可以开始读一本计算机图形学的入门书了。
下一个重要的用于计算机图形学的数学——线性代数,多数此类书籍至少包含了一个对线性代数的简要介绍。
推荐的参考书:
Computer Graphics:
Principles and Practice
James Foley, Andries van Dam, Steven Feiner, John Hughes
Addison-Wesley
[虽然厚重,可是我很喜欢]
线性代数
线性代数的思想贯穿于计算机图形学。
事实上,只要牵涉到几何数值表示法,就常常抽象出例如x,y,z坐标之类的数值,我们称之为矢量。
图形学自始至终离不开矢量和矩阵。
用矢量和矩阵来描述旋转,平移,或者缩放是再好不过了。
高中和大学都有线性代数的课程。
只要想在计算机图形学领域工作,就应该打下坚实的线性代数基础。
我刚才提到,许多图形学的书都有关于线性代数的简要介绍——足够教给你图形学的第一门课。
推荐的参考书:
Linear Algebra and Its Applications
Gilbert Strang
Academic Press
微积分学
微积分学是高级计算机图形学的重要成分。
如果打算研究图形学,我强烈建议你应该对微积分学有初步认识。
理由不仅仅是微积分学是一种很有用的工具,还有许多研究者用微积分学的术语来描述他们的问题和解决办法。
另外,在许多重要的数学领域,微积分学被作为进一步学习的前提。
学习了基本代数之后,微积分学又是一种能为你打开多数计算机图形学与后继的数学学习之门的课程。
微积分学是我介绍的最后一个中学课程,以下提及的科目几乎全部是大学的课程。
微分几何学
微分几何学研究支配光滑曲线,曲面的方程组。
如果你要计算出经过某个远离曲面的点并垂直于曲面的矢量(法向矢量)就会用到微分几何学。
让一辆汽车以特定速度在曲线上行驶也牵涉到微分几何学。
有一种通用的绘制光滑曲面的图形学技术,叫做“凹凸帖图”,这个技术用到了微分几何学。
如果要着手于用曲线和曲面来创造形体(在图形学里称之为建模)你至少应该学习微分几何学的基础。
推荐的参考书:
Elementary Differential Geometry
Barrett O'Neill
Academic Press
数值方法
几乎任何时候,我们在计算机里用近似值代替精确值来表示和操作数值,所以计算过程总是会有误差。
而且对于给定的数值问题,常常有多种解决的方法,一些方法会更块,更精确或者对内存的需求更少。
数值方法研究的对象包括“计算方法”和“科学计算”等等。
这是一个很广阔的领域,而且我将提及的其他几门数学其实是数值方法的一些分支。
这些分支包括抽样法理论,矩阵方程组,数值微分方程组和最优化。
推荐的参考书:
Numerical Recipes in C:
The Art of Scientific Computing
William Press, Saul Teukolsky, William Vetterling and Brian Flannery
Cambridge University Press
[这本参考书很有价值可是很少作为教材使用]
抽样法理论和信号处理
在计算机图形学里我们反复使用储存在正规二维数组里的数字集合来表示一些对象,例如图片和曲面。
这时,我们就要用抽样法来表示这些对象。
如果要控制这些对
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数学 计算机 编程 中的 应用
![提示](https://static.bdocx.com/images/bang_tan.gif)