第六章 Maple程序设计
- 格式:doc
- 大小:446.00 KB
- 文档页数:53
第六章Maple程序设计教学目的:学习并掌握计算机代数系统Maple下的算法设计和程序设计原理和方法,包括基本程序结构、子程序求值、程序的嵌套以及程序的调试。
教学要求:掌握算法设计和程序设计原理和基本方法。
重点内容:算法设计,程序设计。
难点内容:算法设计,程序设计。
前面, 我们使用的是Maple 的交互式命令环境. 所谓交互式命令环境, 就是一次输入一条或几条命令, 然后按回车, 这些命令就被执行了, 执行的结果显示在同一个可执行块中. 对于大多数用户来说, 利用交互式命令环境解决问题已经足够了, 但如果要解决一系列同一类型的问题或者希望利用Maple 编写需要的解决特定问题的函数和程序, 以期更加充分地利用Maple 的强大功能, 提高大规模问题的计算效率, 进行一定的程序设计是必要的.程序设计主要包括两个方面: 行为特性的设计与结构特性的设计. 所谓行为特性的设计, 通常是指将解决问题的过程的每一个细节准确地加以定义, 并且还应当将全部的解题过程用某种工具完整地描述出来, 这一过程也称为算法的设计. 而结构特性设计是指为问题的解决确定合适的数据结构.幸运的是, Maple 自身提供了一套编程工具, 即Maple 语言. Maple 语言实际上是由Maple 各种命令以及一些简单的过程控制语句组成的.1编程基础1.1算子所谓算子, 是从一个抽象空间到另一个抽象空间的函数. 在数学上算子的含义通常是函数到函数的映射. 在Maple 中, 算子常用“箭头”记号定义(也称箭头操作符): > f:=x->a*x*exp(x);:= f → x a x e x> g:=(x,y)->a*x*y*exp(x^2+y^2);:= g → (),x y a x y e () + x 2y 2另外, 函数unapply 也可以从表达式建立算子:> unapply(x^2+1,x);→ x + x 21> unapply(x^2+y^2,x,y);→ (),x y + x 2y 2当我们依次把算子f 作用到参数0, a, x^2+a 时即可得平常意义上的函数值:> f:=t->t*sin(t);:= f → t t ()sin t> f(0);> f(a);a ()sin a> f(x^2+a);() + x 2a ()sin + x 2a上述结果是函数作用的例子. 而最后一个结果)sin()(22a x a x ++实际上是算子f 与算子g:=t->t^2+a 复合后再作用到参数x 的结果.从数学上讲, 作用与复合是不同的,它们产生的结果是有区别的, 但在使用它们时, 两者还是有些重叠的. 在Maple 中, 可以依赖于语法把它们区分开:(1) 当复合两个算子时, 结果仍是算子, 两个算子的定义域必须是相容的;(2) 当把一个算子作用于一个参数(参数必须在算子的定义域中)时, 结果是一个表达式;(3) 在Maple 中,函数作用的语法是使用括号( ),如函数f 作用到参数u 写作f(u). 而复合算子的符号是@,多重复合时使用符号@@.通过进一步的例子可以清楚区分作用与复合的功能: f 和g 复合的结果是算子))((:t g f t g f =, 而把这个算子作用到参数x 得到表达式f (g (x )). 例如, )exp(),sin(u u g t t f =+=ϕ, 则))sin(exp(:ϕ+=z z g f 是一个算子, 而))sin(exp()((ϕ+=x x g f 是一个表达式, 因为x 是一个实数. 试比较下述两例: > D(g@f);()@()()D g f ()D f> D(g*h);+ ()D g h g ()D h另外一个应引起注意的问题是算子(函数)与表达式的异同,在第一章2.2.2中曾探讨过函数与表达式的区别,这里再通过几个例子说明其中的微妙差异:> f1:=x^2+1;> f2:=y^2+1;:= f1 + x 21:= f2 + y 21> f3:=f1+f2;:= f3 + + x 22y 2再看下面的例子:> g1:=x->x^2+1;> g2:=y->y^2+1;:= g1 → x + x 21:= g2 → y + y 21> g3:=g1+g2;:= g3 + g1g2与前面例子不同的是,两个算子(函数)g1, g2相加的结果依然是函数名g3,出现这个问题的主要原因是g1与g2分别为x ,y 的函数,Maple 认为它们的定义域不相容. 要得到与前例的结果,只需稍作改动:> g3:=g1(x)+g2(y);:= g3 + + x 22y 2下面的例子想说明生成Maple 函数的两种方式“箭头操作符”及“unapply ”之间微妙的差异:> restart: a:=1: b:=2: c:=3:> a*x^2+b*x+c;+ + x 22x 3> f:=unapply(a*x^2+b*x+c,x);:= f → x + + x 22x 3> g:=x->a*x^2+b*x+c;:= g → x + + a x 2b x c由此可见,f 中的a,b,c 已经作了代换,而g 中则显含a,b,c 。
数学应用软件实验指导书石家庄铁道学院数学实验室1前言随着计算机科学的飞速发展,以及工程计算的迫切需求,计算机符号代数系统(Computer Algebra System, CAS)得到了广泛的应用及拓展。
一般按功能的不同,将此系统分为两大类:专用系统和通用系统。
专用符号代数系统是特别为解决物理、化学或数学中某一方面问题而编写的。
例如天体物理方面的CAMAL;针对核物理的SCHOOHSCHIP;应用于物理化学,计算分子结构、反应动力学的GAUSSIAN;以及分析微分方程的DELIA等等。
通用符号系统则是针对普遍的应用领域而开发出来的,包含大量的数据结构与数学函数包。
通用系统软件的执行方式一般有两种,一种是输入一条命令、输出一条结果式的命令行方式。
虽然不同软件的执行命令不尽相同,但一般都具有数值计算、符号计算、图形处理这3种功能;另一种是类似FORTRAN、C语言的编程模式。
不同的软件编程语言也不尽相同,但能够实现的功能类似。
概括起来,计算机符号代数系统可以应用到以下的领域:1.推导的工具。
符号系统可以出色地完成科研、工程中所遇到的复杂公式推导与验证工作,不仅可以避免人工推导过程中可能会出现的错误,而且显著地提高了工作效率。
2.数学实验。
由于推导工作的简化,可以通过对符号的变换与处理,为数学研究提供一种类似“实验室”的环境,通过不同的方法可能出现的结果。
3.辅助教学。
符号代数系统的易学易用为学生和老师提供了很好的学习帮助系统。
许多问题借助计算机将得到更快更好的解决。
同时为制作课件和练习系统提供了方便。
一般来讲,选择一个好某个软件之后,应以这个软件为主,尽量熟悉和精通,这样比较节省精力。
但就象俗话说的“尺有所短,寸有所长”,由于每个软件都有长处,同时又有某种缺陷,所以,学习中还要博众家之长,以备用时随心所欲。
下面,我们根据通用软件Maple, MATLAB, MathCAD, Mathematica的不同特点,选用每个软件中最适合解决数学计算或应用的部分进行学习。
目录摘要 ............................................................................ - 3 -第一章题目的意义...................................................... - 4 -第二章理论分析......................................................... - 4 -2.1位移法的基本概念.. (4)2.2平面桁架分析的基本问题 (7)第三章程序设计框图..................................................- 12 -第四章程序代码........................................................- 13 -4.1计算平面桁架位移法的程序代码 .. (13)第五章应用..............................................................- 16 -5.1例一 .. (16)5.2例二 (19)第六章结论······························································- 22 -参考文献 ·····································································- 22 -平面桁架位移法计算的MAPLE程序设计摘要本文利用位移法编写MAPLE程序来计算平面桁架各节点位移、各杆的轴力。
107Maple V Release 5 起步与进阶。
108.和别的语言不同,当我们利用Maple 进行二维或者三维绘图时,Maple 可以自动地决定所需的点数、坐标轴的位置、标尺的数字、图形的颜色等等繁杂的设置,在默认状态下就可以绘制出令人满意的图形。
当然,你也可以自己设定各种不同的绘图设置,比如更改绘图的坐标系(以画出极坐标、球坐标、或柱坐标下的图形),或者绘图的点数。
下面,我们就由浅入深地介绍Maple 中的绘图方法。
6.1 二维基本图形绘制在Maple 中,单变量函数曲线的绘制可以使用函数plot 。
例如,我们需要绘制函数)sin()(32x e x f x π−=在区间[-2,2]上的图形,我们可以这样来实现。
首先用箭头操作符定义函数:然后,调用plot 函数。
键入命令后,所绘制的图形会立即出现在同一个可执行块中。
Maple V Release 5也支持把图形单独绘制在一个窗口中,如图 6.1所示,只需要在菜单Option | Plot Display 选择Window 即可。
一般地,函数plot 的调用格式为plot (f , a..b, options )。
其中,f 是需要绘制的函数,a..b 是自变量的变化范围,options 是可选参数,用它可以控制图形的绘制,我们将在下一节中详细介绍。
除了可以绘制函数的图形外,plot 也可以绘制表达式表示的函数图形,调用格式为plot (expr , x = a..b, options )。
其中,expr 是表达式(相信读者一定知道表达式和函数间的区别了),x 是表达式中的自变量,因为表达式中没有自变量的信息(甚至可以是多变量的表达式),所以必须指定自变量,并用等式形式给出自变量的变化范围。
第六章 Maple绘图。
109.图6.1 在窗口中绘图这些基本的绘图功能,Maple 和其他的树脂绘图工具(比如Matlab 、Origin 等)并没有什么区别。
maple 简单编程
Maple是一种流行的数学软件,也可以用来编写简单的程序。
下面是一个简单的Maple程序示例,用于计算圆的面积和周长:
```
with(vectores):
# 定义向量
x := [1, 0]:
y := [0, 1]:
# 定义圆心
center := [0, 0]:
# 定义半径
radius := 1:
# 定义圆的方程
circle := x*x + y*y - 2*x - 2*y + 1 = 0:
# 计算周长
circumference := 2*pi*radius:
# 计算面积
area := pi*radius^2:
# 输出结果
writeln(circumference, area);
```
在这个程序中,我们首先定义了向量x和y,然后定义了圆心和半径。
接着,我们定义了圆的方程,并计算了圆的周长和面积。
最后,我们使用writeln函数输出了结果。
需要注意的是,Maple是一种高级数学软件,支持许多高级数学函数和算法。
如果您需要编写更复杂的程序,建议查阅Maple的官方文档或参考相关教程。
(第六章M aple的绘图功能)§6.3 三维图形绘制三绘图原理上,三维图形与二维图形没有本质的区别,但由于涉及到如何在二维的显示设备上表示的问题,在图形学中,三维图形增加了投影方式的选择。
然而在Maple系统中,用户却不需要考虑投影方面的问题,因为几乎所有的三维图形都是以斜投影的方式表示的。
用户可以改变的,只有物体的方向以及视点的远近。
由于三维图形绘制时可以选择的参数同二维图形基本类似,所以在对plot3d函数做基本介绍后,本节的重点将转移到一些plot程序库附带的其他三维图形绘制函数上,比如等高线、密度图等的绘制。
6.3.1 基本三维函数图形的生成由于现实中人们熟知的三维图形一般并非简单函数可以生成的,即使可以表示,也涉及到很多参数的设定,所以在实际三维绘图中,plot3d函数并不像plot函数那样常用。
一般只是用它对三维函数曲线进行绘绘制。
它的使用方法同plot函数几乎完全一样,比如利用简化输入绘制一个三维曲面:> f:=(x,y)->cos(x*y):> plot3d(f,-3..3,-2..2,orientation=[160,50]);之所以称这种输入方法为简化输入,因为我们在输入坐标范围的时候,并不是按照“x=a..b,y=c..d”这种规则形式书写的,而是直接写成“a..b,c..d”的形式。
注意这样的输入方法只对函数变量定义为“x,y”的形式有效,系统会自动将坐标x轴的范围定义为“a..b”,而将y轴定义为“c..d”。
同样,在plot函数中也可以对变量被定义为x的函数使用这种简化输入法。
相对于二维的plot函数,plot3d在坐标轴的形式,曲线、曲面的式样等一些方面有新的参数。
在上例中使用的orientation参数就是其中之一,它可以确定用户的观察角度。
“[ ]”中的数值分别对应三维工具栏中θ角与ϕ角。
由于这些参数同plot 函数中的参数大同小异,本节不再讲述。
第五章程序设计§5.1 简单的程序设计前面已经用过很多Maple的内部函数和程序包带的外部程序。
现在我们要学着自己建立函数了。
先来看一个关于log函数的源代码,这样能熟悉一下Maple编程的一般规则。
> interface(verboseproc=2): 先调用函数interface,设置参数> readlib(log); 调log的源代码。
改log为sin等,就能看这些函数的源代码::x algebraicproc()local;a`Copyright (c) 1992 by the University of Waterloo. All rights reserved.`option;`expecting 1 argument, got `nargsERROR ||if thennargs1()≠elif thenindexedtype,procname''()a()op procname;:=''if thenalgebraic error "invalid index"a[][]not ()type,`expecting 1 argument, got `nargsERROR ||elif then≠nargs1()()complex floatelif thentype,x''complex float()ortype,a''()()ln x()ln a +()Digits2/()evalf()evalf,elseln a()ln x()/end ifelseln x()end ifend proc5.1.1 过程和函数过程和函数差得不是很多,它们都可以实现对方的功能,如果没有特别说明,我们对这两种概念将不做区分。
一个Maple语言的过程定义的格式如下:proc(argseq)local lseq;global gseq;1options oseq;description stringseq;statseqend proc一个过程一定是以proc开头,以end proc(或)结束。
maple 编程语言类型-回复Maple 编程语言类型Maple 是一种高级的编程语言,用于科学计算和数学建模。
它提供了丰富的数学函数库,可以进行符号计算、数值计算和数据可视化。
Maple 具有类似于MATLAB 的矩阵操作能力,以及类似于Python 的面向对象编程特性。
本文将深入讨论Maple 的编程语言类型。
1. 命令式编程:Maple 是一种命令式编程语言,其中的指令按照特定的顺序执行。
命令式编程强调计算机中指令的顺序和执行方式,开发人员需要详细描述每个操作步骤。
在Maple 中,开发者可以使用内置函数和运算符来实现这些操作。
例如,使用`solve` 函数来求解方程,使用`int` 函数来进行积分计算。
2. 符号计算:Maple 的一个重要特点是其强大的符号计算能力。
符号计算是一种处理数学表达式的方法,它可以保留变量和未知数的符号形式,而不是仅仅进行数值计算。
这使得开发者能够进行精确的数学推导和计算。
在Maple 中,通过定义变量和使用内置函数,开发者可以进行代数运算、微积分、线性代数等数学操作。
3. 数值计算:Maple 还支持数值计算,它可以在处理数学表达式时对变量进行数值替代,以获得近似的数值结果。
这对于处理复杂的数学公式和方程组非常有用。
Maple 提供了大量的数值计算函数和算法,例如求解方程组的数值解、数值积分和数值微分等。
4. 函数式编程:Maple 具有函数式编程的特性,它支持函数作为一等对象。
这意味着函数可以像其他数据类型一样进行传递和操作。
开发者可以定义自己的函数,并将其用作参数传递给其他函数或赋值给变量。
这种函数式编程的特性使得Maple 具有优雅而强大的抽象能力,可以更方便地进行代码复用和模块化。
5. 面向对象编程:与函数式编程相反,Maple 还支持面向对象编程。
开发者可以定义类和对象,通过封装属性和方法来创建复杂的数据结构和行为。
这种面向对象的编程方式使得代码更加易于理解和维护,并提供了更高级的抽象和封装能力。
maple工程计算Maple是一款强大的数学软件,提供了丰富的工程计算功能。
在工程计算中,Maple可以帮助我们进行各种数学计算、模拟实验、数据分析等任务。
本文将介绍Maple在工程计算中的应用,并根据不同的应用场景,总结了一些使用Maple进行工程计算的常用方法和技巧。
一、Maple在工程计算中的应用1.数学建模:Maple是一个非常强大的数学计算软件,它可以帮助我们进行各种数学建模工作。
通过Maple,我们可以建立各种数学模型,如微分方程模型、优化模型等。
利用Maple的求解器,我们可以方便地求解这些数学模型,并得到准确的结果。
2.仿真实验:Maple提供了强大的仿真功能,可以帮助我们进行各种仿真实验。
例如,我们可以用Maple建立电路模型,并模拟电路的运行情况;或者我们可以用Maple建立机械系统模型,并模拟机械系统的运动轨迹。
通过仿真实验,我们可以快速了解系统的性能特点,并进行参数优化。
3.数据分析:Maple也是一款强大的数据分析工具。
它提供了丰富的数据处理和分析函数,可以帮助我们对大量的数据进行快速的计算和分析。
例如,我们可以用Maple进行数据的统计分析、拟合曲线、数据可视化等工作。
通过数据分析,我们可以深入了解数据的规律和特点,并对数据进行更加准确的分析和预测。
4.优化设计:Maple还提供了优化算法,可以帮助我们进行优化设计。
例如,我们可以利用Maple进行参数优化,找到系统的最优解。
通过优化设计,我们可以提高系统的性能,降低成本,提高效率。
二、使用Maple进行工程计算的常用方法和技巧1.符号计算:Maple可以进行符号计算,这对工程计算非常有帮助。
符号计算可以处理包含未知变量的表达式,并进行符号化简、方程求解、微分计算等。
利用Maple的符号计算功能,我们可以得到更加精确的结果。
2.数值计算:Maple也可以进行数值计算,这对于处理大规模的数据和复杂的计算任务非常有效。
在进行数值计算时,我们可以设置合适的计算精度,提高计算速度。
第六章Maple程序设计教学目的:学习并掌握计算机代数系统Maple下的算法设计和程序设计原理和方法,包括基本程序结构、子程序求值、程序的嵌套以及程序的调试。
教学要求:掌握算法设计和程序设计原理和基本方法。
重点内容:算法设计,程序设计。
难点内容:算法设计,程序设计。
前面, 我们使用的是Maple 的交互式命令环境. 所谓交互式命令环境, 就是一次输入一条或几条命令, 然后按回车, 这些命令就被执行了, 执行的结果显示在同一个可执行块中. 对于大多数用户来说, 利用交互式命令环境解决问题已经足够了, 但如果要解决一系列同一类型的问题或者希望利用Maple 编写需要的解决特定问题的函数和程序, 以期更加充分地利用Maple 的强大功能, 提高大规模问题的计算效率, 进行一定的程序设计是必要的.程序设计主要包括两个方面: 行为特性的设计与结构特性的设计. 所谓行为特性的设计, 通常是指将解决问题的过程的每一个细节准确地加以定义, 并且还应当将全部的解题过程用某种工具完整地描述出来, 这一过程也称为算法的设计. 而结构特性设计是指为问题的解决确定合适的数据结构.幸运的是, Maple 自身提供了一套编程工具, 即Maple 语言. Maple 语言实际上是由Maple 各种命令以及一些简单的过程控制语句组成的.1编程基础1.1算子所谓算子, 是从一个抽象空间到另一个抽象空间的函数. 在数学上算子的含义通常是函数到函数的映射. 在Maple 中, 算子常用“箭头”记号定义(也称箭头操作符): > f:=x->a*x*exp(x);:= f → x a x e x> g:=(x,y)->a*x*y*exp(x^2+y^2);:= g → (),x y a x y e () + x 2y 2另外, 函数unapply 也可以从表达式建立算子:> unapply(x^2+1,x);→ x + x 21> unapply(x^2+y^2,x,y);→ (),x y + x 2y 2当我们依次把算子f 作用到参数0, a, x^2+a 时即可得平常意义上的函数值:> f:=t->t*sin(t);:= f → t t ()sin t> f(0);> f(a);a ()sin a> f(x^2+a);() + x 2a ()sin + x 2a上述结果是函数作用的例子. 而最后一个结果)sin()(22a x a x ++实际上是算子f 与算子g:=t->t^2+a 复合后再作用到参数x 的结果.从数学上讲, 作用与复合是不同的,它们产生的结果是有区别的, 但在使用它们时, 两者还是有些重叠的. 在Maple 中, 可以依赖于语法把它们区分开:(1) 当复合两个算子时, 结果仍是算子, 两个算子的定义域必须是相容的;(2) 当把一个算子作用于一个参数(参数必须在算子的定义域中)时, 结果是一个表达式;(3) 在Maple 中,函数作用的语法是使用括号( ),如函数f 作用到参数u 写作f(u). 而复合算子的符号是@,多重复合时使用符号@@.通过进一步的例子可以清楚区分作用与复合的功能: f 和g 复合的结果是算子))((:t g f t g f =, 而把这个算子作用到参数x 得到表达式f (g (x )). 例如, )exp(),sin(u u g t t f =+=ϕ, 则))sin(exp(:ϕ+=z z g f 是一个算子, 而))sin(exp()((ϕ+=x x g f 是一个表达式, 因为x 是一个实数. 试比较下述两例: > D(g@f);()@()()D g f ()D f> D(g*h);+ ()D g h g ()D h另外一个应引起注意的问题是算子(函数)与表达式的异同,在第一章2.2.2中曾探讨过函数与表达式的区别,这里再通过几个例子说明其中的微妙差异:> f1:=x^2+1;> f2:=y^2+1;:= f1 + x 21:= f2 + y 21> f3:=f1+f2;x22y2f3 + +:=再看下面的例子:> g1:=x->x^2+1;> g2:=y->y^2+1;x21:=x +g1 →y21y +:=g2 →> g3:=g1+g2;g3 +g1g2:=与前面例子不同的是,两个算子(函数) g1, g2相加的结果依然是函数名g3,出现这个问题的主要原因是g1与g2分别为x,y的函数,Maple认为它们的定义域不相容. 要得到与前例的结果,只需稍作改动:> g3:=g1(x)+g2(y);x22y2g3 + +:=下面的例子想说明生成Maple函数的两种方式“箭头操作符”及“unapply”之间微妙的差异:> restart: a:=1: b:=2: c:=3:> a*x^2+b*x+c;x22x3+ +> f:=unapply(a*x^2+b*x+c,x);x22x3x + +f →:=> g:=x->a*x^2+b*x+c;a x2b x c:=x + +g →由此可见,f中的a,b,c已经作了代换,而g中则显含a,b,c。
再看下面实验:> f(x); g(x);+ +x22x3x22x3+ +f与g两者相同,再对其微分:> D(f); D(g);→ x + 2x 2→ x + 2a x b再改变常数c 的值,观察f 与g 的变化:> c := 15;:= c 15> f(x); g(x);+ + x 22x 3+ + x 22x 15由此可见,在利用Maple 进行函数研究时,对同一问题应该用不同方法加以校验,而这一切的支撑是数学基础!1.2 编程初体验利用算子可以生成最简单的函数—单个语句的函数, 但严格意义上讲它并非程序设计, 它所生成的数据对象是子程序. 所谓子程序,简单地说, 就是一组预先编好的函数命令, 我们由下面的简单程序来看看Maple 程序的结构:> plus:=proc(x,y)x+y;end;这个程序只有2个参数, 在程序内部它的名称是x , y, 这是Maple 最简单的程序结构, 仅仅在proc ( )和end 中间加上在计算中需要的一条或者多条命令即可, Maple 会把最后一个语句的结果作为整个子程序的返回结果, 这一点需要引起注意. 再看下例: > P:=proc(x,y)x-y;x*y;x+y;end:> P(3,4);7显然, 尽管程序P 有三条计算命令,但返回的只是最后一个语句x+y;的结果. 要想输出所有的计算结果,需要在程序中增加print 语句:> P:=proc(x,y)print(x-y);print(x*y);print(x+y);end:> P(3,4);-1127再看下面几个例子:> for i from 2 to 6 doexpand((x+y)^i );od;x22x y y2+ +x33x2y3x y2y3+ + +x44x3y6x2y24x y3y4+ + + +x55x4y10x3y210x2y35x y4y5+ + + + +x66x5y15x4y220x3y315x2y46x y5y6+ + + + + +> F:=proc(n::integer)if n mod 12=0 then trueelse falsefiend:> F(123^123), F(1234567890^9);,false true从上面几个简单的例子可以看出Maple子程序主要包含以下一些内容:(i)把定义的子程序赋值给程序名procname, 以后就可以用子程序名procname来调用程序;(ii)子程序一律以proc( )开头, 括号里是程序的输入参数,如果括号中什么都没有, 表示这个子程序没有任何输入参数;(iii)子程序中的每一个语句都用分号(或冒号)分开(这一点不是主要的, 程序设计时, 在可能的时候—过程当中的最后一个语句、for-循环、if语句中的最后一个语句省略终结标点也是允许的, 这并不是为了懒惰, 而是因为在终结语句后面插入一个语句产生的影响要比仅仅执行一个新语句产生的影响大);(iv)在定义完子程序之后, Maple会显示它对该子程序的解释(除非在end后用冒号结束), 它的解释和你的定义是等价的, 但形式上不一定完全相同;(v)Maple会自动地把除了参数以外的变量都作为局部变量(local variable), 这就是说, 它们仅仅在这个子程序的定义中有效, 和子程序以外的任何同名变量无关.在定义了一个子程序以后, 执行它的方法和执行任何Maple系统子程序一样—程序名再加上一对圆括号( ), 括号中包含要调用的参数, 如果子程序没有参数, 括号也是不能省略的.除了上面给出的程序设计方法外,在Maple中还可以直接由“->”(箭头)生成程序, 如下例:> f:=x->if x>0 then x else -x fi;<0x x-xoperator arrow if then else end ifx option;:=f proc()end proc,> f(-5),f(5);,55甚至于程序名也可以省略,这种情况通常会在使用函数map时遇到:> map(x->if x>0 then x else -x fi,[-4,-3,-2,0,1]);43201,,,,[]如果需要察看一个已经定义好的子程序的过程, 用eval命令, 查看Maple中源程序(如factor函数)使用下述组合命令:interface(verboseproc=2);print(factor);1.3 局部变量和全局变量Maple中的全局变量, 是指那些在交互式命令环境中定义和使用的变量, 前面所使用的变量几乎都属于全局变量. 而在编写子程序时, 需要定义一些只在子程序内部使用的变量, 称其为局部变量. 当Maple执行子程序时, 所有和局部变量同名的全局变量都保持不变, 而不管在子程序中给局部变量赋予了何值. 如果要把局部变量定义为全局变量, 需要用关键词global在程序最开始加以声明, 而局部变量则用local声明, 虽然这是不必要的, 但在程序设计时, 声明变量是有一定好处的.下面通过实例演示局部变量与全局变量的不同. 为了更清楚地观察子程序对全局变量的影响, 在子程序外先设定一个变量a的值:> a:=1;a1:=>>>>>>系.1.4在所有程序中都有三个有用的变量:nargs, args与procname. 前两个给出关于调用参量的信息: nargs变量是调用的实际参量的个数, args变量是包含参量的表达式序列, args的子序列通过范围或数字的参量选取. 例如, 第i个参量被调用的格式为: args[i]. nargs, args变量通常在含有可选择参量的程序中使用. 下面看一个例子:> p:=proc( )local i;RETURN(nargs,[seq(i^3,i=args)])>>>>>2 基本程序结构所有的高级程序设计语言都具有程序结构, 因为为了完成一项复杂的任务, 仅仅按照语句顺序依次执行是远远不够的, 更需要程序在特定的地方能够跳转、分叉、循环, ……, 与此同时, 程序结构就产生了.2.1分支结构(条件语句)所谓分支结构, 是指程序在执行时, 依据不同的条件, 分别执行两个或多个不同的程序块, 所以常常称为条件语句. if条件结构的语法为:if逻辑表达式1(条件1) then 程序块1elif逻辑表达式2(条件2) then程序块2else 程序块3fi;其中, fi是条件语句的结束标志, 也可以写作end if.下面是一个判断两个数中较大者的例子:> bigger:= proc(a,b)if a>=b then aelse bfiend;再如下例:> ABS:=proc(x)if x<0 then -xelse x;fi;end;显然,这个绝对值函数的简单程序, 对于任意实数范围内的数值型变量计算都是没有问题的, 但对于非数值型的参数则无能为力. 为此,我们需要在程序中添加一条判断参数是否为数值型变量的语句:> ABS:=proc(x)if type(x,numeric) thenif x<0 then -x else x;fi;else'ABS'(x);fi;end:这里, 我们用到一个if语句的嵌套, 也就是一个if语句处于另一个if语句当中. 这样的结构可以用来判断复杂的条件. 我们还可以用多重嵌套的条件结构来构造更为复杂的函数, 例如下面的分段函数:> HAT:=proc(x)if type(x,numeric) thenif x<=0 then 0;elseif x<=1 then x;else 0;fi;fi;else'HAT'(x);fi;end;尽管在上面的程序中我们用了不同的缩进来表示不同的层次关系, 这段程序还是很难懂. 对于这种多分支结构, 可以用另一种方式书写, 只需在第二层的if语句中使用elif, 这样就可以把多个分支形式上写在同一个层次中, 以便于阅读.> HAT:=proc(x)if type(x,numeric) thenif x<=0 then 0;elif x<=1 then x;else 0;fi;else'HAT'(x);fi;end;和许多高级语言一样, 这种多重分支结构理论上可以多到任意多重.再来看看前面的绝对值函数的程序, 似乎是完美的, 但是, 对于乘积的绝对值则没有办法, 下面用map命令来修正, 注意其中的type(…, `*`)是用来判断表达式是否为乘积, 进而对其进行化简.> ABS:=proc(x)if type(x,numeric) thenif x<0 then -x else x fi;elif type(x,`*`) then map(ABS,x);else'ABS'(x);fi;end:> ABS(-1/2*b);1 2() ABS b分段函数是一类重要的函数,条件语句在定义分段函数时具有明显的优越性,下面学习几个实例:(1)> f:=proc( x )if x<0 then x^2+1 else sin(Pi*x) fi; end;(2) = ()g x ⎧⎩⎪⎪⎪⎪⎪⎨ + x 2x ≤ x 0()sin x < x 3π - + - + x 26πx 9π2x 3π ≤ 3πx>g:=proc(x)if x<=0 then x^2+x elseif x<3*Pi then sin(x) elsex^2-6*x*Pi+9*Pi^2-x+3*Pi fi fi end;2.2 for 循环在程序设计中, 常常需要把相同或者类似的语句连续执行多次, 此时, 通过for 循环结构可以更便捷地编写程序. 试看下面几个例子: ① 求1至5自然数的和: > total:=0:for i from 1 to 5 do total:=total+i: od;:= total 1 := total 3 := total 6 := total 10 := total 15② 列示2,4,6,8,10及其平方数、立方数: > for i from 2 to 10 by 2 do'i'=i, 'i^2'=2^i, 'i^3'=i^3;= ()f x { + x 21 < x 0()sin πx ≤ 0xod;i38i24 =i2 =,,=i364i216 =i4 =,,=i3216i264 =i6 =,,=i8 =i3512i2256 ==,,i21024 =i31000i10 ==,,③列示第100到第108个素数(第1个素数是2):>for j from 100 to 108 doprime[j]=ithprime(j);od;prime541=100547prime=101557prime=102563prime=103prime569=104prime571=105577prime=106587prime=107prime=593108④列示5到10的阶乘及其因数分解:> for n in seq(i!,i=5..10) don=ifactor(n);od;=120()23()3()5720()24()32()5=5040()24()32()5()7==40320()27()32()5()7362880()27()34()5()7==3628800()28()34()52()7⑤一个复杂的幂指函数生成:>f:=proc(x,n)local i, t;t:=1;for i from 1 to n dot:=x^(t^x);od;t;end:> f(x,10);x ⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎪⎪⎪⎛⎝⎫⎭⎪⎪⎪⎪⎪x⎛⎝⎫⎭⎪⎪⎪⎛⎝⎫⎭⎪⎪x()x xxxxxxxxx通过上述例子可以看出,Maple的for循环结构很接近于英语语法. 在上面例子中, i 称为循环变量, 用于循环计数, do后面的部分, 称为循环体, 就是需要反复执行的语句, 可以是一条语句, 也可以是多条语句. 在循环体中, 也可以引用循环变量. 循环体的结束标志, 也就是整个for循环结构的结束标志, 是字母“od”(也可以写作end do). for循环结构的语法可总结为:for循环变量from初始值to终止值(by步长) do循环体od在for循环结构中,初始值和终了值必须是数值型的, 而且必须是实数, 如果初始值是1, 可以省略不写, 而步长用by引出.对于上面程序中的重复循环似乎可有可无, 但实际科学计算中, 重复次数往往成千上万, 或者重复的次数无法确定, 循环就必不可少了. 下面再看一个实用程序—从1到n 的自然数的求和程序:> SUM:=proc(n)local i, total; total:=0;for i from 1 to n do total:=total+i; od; end;> SUM(1000);500500该程序仅仅具有练习例举的意义, 因为在Maple 中像这样一个问题只需要一个简单语句就可以完成:> Sum(n,n=1..1000)=sum(n,n=1..1000);= ∑= n 11000n 500500更一般地, 对于确定的求和可用add 命令(该命令无惰性函数形式): > add(n,n=1..1000);500500再看下面一个动画制作例子(图略去): > for i from -20 to 30 dop||i:=plots[implicitplot](x^3+y^3-5*x*y=1-i/8,x=-3..3,y=-3..3,numpoints=800,tickmarks=[2,2] )od:> plots[display]( p||(-20..30), insequence=true );2.3 while 循环for 循环在那些已知循环次数, 或者循环次数可以用简单表达式计算的情况下比较适用. 但有时循环次数并不能简单地给出, 我们要通过计算, 判断一个条件来决定是否继续循环, 这时, 可以使用while 循环. while 循环标准结构为:while 条件表达式 do循环体 odMaple 首先判断条件是否成立, 如果成立, 就一遍遍地执行循环体, 直到条件不成立为止.下面看一个简单的程序, 是用辗转相除法计算两个自然数的最大公约数( Euclidean 算法).> GCD:=proc(a::posint, b::posint)local p,q,r;p:=max(a,b);q:=min(a,b);r:=irem(p,q);while r<>0 dop:=q;q:=r;r:=irem(p,q);od;q;end:> GCD(123456789,987654321);9在上面程序中的参数a、b后面的双冒号“::”指定了输入的参数类型. 若类型不匹配时输出错误信息. 再看下面一个扩展Euclidean算法的例子:>mygcdex:= proc(a::nonnegint, b::nonnegint, x::name, y::name)local a1,a2,a3,x1,x2,x3,y1,y2,y3,q;a1:=a; a2:=b;x1:=1; y1:=0;x2:=0; y2:=1;while (a2<>0) doa3:= a1 mod a2;q:= floor(a1/a2);x3:=x1-q*x2;y3:=y1-q*y2;a1:=a2; a2:= a3;x1:=x2; x2:= x3;y1:=y2; y2:= y3;od;x:=x1; y:=y1;RETURN(a1)end:> mygcdex(2^10,6^50,'x','y');10242.4递归子程序正如在一个子程序中我们可以调用其他的子程序一样(比如系统内部函数, 或者已经定义好的子程序), 一个子程序也可以在它的内部调用它自己, 这样的子程序我们称为递归子程序. 关于递归算法及其设计将在下节详述. 在数学中, 用递归方式定义的例子很多, 如Fibonacci 数列:)2(,1,02110≥+===--n f f f f f n n n下面我们在Maple 中利用递归子程序求Fibonacci 数列的第n 项: > F:=proc(n::nonnegint)::listif n<=1 then n; elseF (n-1)+F (n-2); fi; end:> seq(F (i),i=0..19);,,,,,,,,,,,,,,,,,,,01123581321345589144233377610987159725844181> F(20);6765但是, 应用上述程序计算F(2000) 时则不能进行, 原因是要计算F(2000), 就先得计算F(1999)、F(1998)、……, 无限制地递归会耗尽系统的堆栈空间而导致错误.由数据结构有关理论知道, 递归程序理论上都可以用循环实现, 比如我们重写上面的程序如下:> F:=proc(n::nonnegint)local temp,fnew,fold,i; if n<=1 then n; elsefold:=0; fnew:=1;for i from 2 to n do temp:=fnew+fold; fold:=fnew; fnew:=temp; od; fi; end:> F(2000):> time(F(2000));.019利用循环, 程序不像前面那么易懂了, 但同时带来的好处也是不可忽视的, 循环结构不仅不会受到堆栈的限制, 而且计算速度得到了很大的提高.我们知道, Maple子程序默认情况下把最后一条语句的结果作为子程序的结果返回. 我们可以用RETURN(或return)命令来显式地返回结果, 比如前面的递归结果可等价地写成:> F:=proc(n::nonnegint)option remember;if n<=1 then RETURN(n);fi;F(n-1)+F(n-2);end:程序进入n<=1的分支中, 执行到RETURN命令就跳出程序, 而不会接着执行后面的语句了. 另外, 使用RETURN命令在一定程度上可以增加程序的可读性.在第二章中曾提到Maple的自动求导功能,下面通过实例说明。