好文档就是一把金锄头!
欢迎来到金锄头文库![会员中心]
电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本

计算机代数系统第6章-程序设计.doc

35页
  • 卖家[上传人]:pu****.1
  • 文档编号:545551428
  • 上传时间:2023-12-26
  • 文档格式:DOC
  • 文档大小:239.51KB
  • / 35 举报 版权申诉 马上下载
  • 文本预览
  • 下载提示
  • 常见问题
    • 第六章 Maple程序设计前面, 我们使用的是Maple的交互式命令环境. 所谓交互式命令环境, 就是一次输入一条或几条命令, 然后按回车, 这些命令就被执行了, 执行的结果显示在同一个可执行块中. 对于大多数用户来说, 利用交互式命令环境解决问题已经足够了, 但如果要解决一系列同一类型的问题或者希望利用Maple编写需要的解决特定问题的函数和程序, 以期更加充分地利用Maple的强大功能, 提高大规模问题的计算效率, 掌握一定的程序设计是必要的. 幸运的是, Maple自身提供了一套编程工具, 即Maple语言. Maple语言实际上是由Maple各种命令以及一些简单的过程控制语句组成的. 1编程基础1.1算子所谓算子, 是从一个抽象空间到另一个抽象空间的函数. 在数学上算子的含义通常是函数到函数的映射. 在Maple中, 算子常用“箭头”记号定义(也称箭头操作符):> f:=x->a*x*exp(x);> g:=(x,y)->a*x*y*exp(x^2+y^2);另外, 函数unapply也可以从表达式建立算子:> unapply(x^2+1,x);> unapply(x^2+y^2,x,y);当我们依次把算子f作用到参数0, a, x^2+a时即可得平常意义上的函数值:> f:=t->t*sin(t);> f(0);> f(a);> f(x^2+a);上述结果是函数作用的例子. 而最后一个结果实际上是算子f与算子g:=t->t^2+a复合后再作用到参数x的结果. 从数学上讲, 作用与复合是不同的,它们产生的结果是有区别的, 但在使用它们时, 两者还是有些重叠的. 在Maple中, 可以依赖于语法把它们区分开: (1) 当复合两个算子时, 结果仍是算子, 两个算子的定义域必须是相容的;(2) 当把一个算子作用于一个参数(参数必须在算子的定义域中)时, 结果是一个表达式; (3) 在Maple中,函数作用的语法是使用括号( ),如函数f作用到参数u写作f(u). 而复合算子的符号是@,多重复合时使用符号@@.通过进一步的例子可以清楚区分作用与复合的功能: f和g复合的结果是算子, 而把这个算子作用到参数x得到表达式f(g(x)). 例如, , 则是一个算子, 而是一个表达式, 因为x是一个实数. 试比较下述两例:> D(g@f);> D(g*h);另外一个应引起注意的问题是算子(函数)与表达式的异同,在第一章2.2.2中曾探讨过函数与表达式的区别,这里再通过几个例子说明其中的微妙差异:> f1:=x^2+1;> f2:=y^2+1;> f3:=f1+f2;再看下面的例子:> g1:=x->x^2+1;> g2:=y->y^2+1;> g3:=g1+g2; 与前面例子不同的是,两个算子(函数) g1, g2相加的结果依然是函数名g3,出现这个问题的主要原因是g1与g2分别为x,y的函数,Maple认为它们的定义域不相容. 要得到与前例的结果,只需稍作改动:> g3:=g1(x)+g2(y);下面的例子想说明生成Maple函数的两种方式“箭头操作符”及“unapply”之间微妙的差异:> x:='x': a:=1: b:=2: c:=3:> a*x^2+b*x+c;> f:=unapply(a*x^2+b*x+c,x);> g:=x->a*x^2+b*x+c; 由此可见,f中的a,b,c已经作了代换,而g中则显含a,b,c。

      再看下面实验:> f(x); g(x); f与g两者相同,再对其微分:> D(f); D(g);再改变常数c的值,观察f与g的变化:> c := 15;> f(x); g(x);由此可见,在利用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);显然, 尽管程序P有三条计算命令,但返回的只是最后一个语句x+y;的结果. 要想输出所有的计算结果,需要在程序中增加print语句:> P:=proc(x,y) print(x-y); print(x*y); print(x+y); end:> P(3,4);再看下面几个例子:> for i from 2 to 6 do expand((x+y)^i );od;> F:=proc(n::integer)if n mod 12=0 then trueelse falsefiend:> F(123^123), F(1234567890^9);从上面几个简单的例子可以看出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;> f(-5),f(5); 甚至于程序名也可以省略,这种情况通常会在使用函数map时遇到:> map(x->if x>0 then x else -x fi,[-4,-3,-2,0,1]);如果需要察看一个已经定义好的子程序的过程, 用eval命令, 查看Maple中源程序(如factor函数)使用下述组合命令:interface(verboseproc=2);print(factor);再看一个更为有用的简单程序:代数方程的参数解。

      该程序在代数方程f(x,y)=0求解中使用了一个巧妙的代换y=tx得到了方程的参数解, 它的主要用途是用来画图、求积分、求微分和求级数. 程序如下:> parsolve:=proc(f,xy::{list(name),set(name)},t::name)local p,x,y;x:=xy[1];y:=xy[2];p:={solve(subs(y=t*x,f),x)}minus{0};map((xi,u,xx,yy)->{xx=xi,yy=u*xi},p,t,x,y)end: 调用该程序可以方便求解:> parsolve(u^2+v^2=a^2,[u,v],t);> f:=randpoly([x,y],degree=3,sparse);> parsolve(f,[x,y],t);1.3 局部变量和全局变量Maple中的全局变量, 是指那些在交互式命令环境中定义和使用的变量, 前面所使用的变量几乎都属于全局变量. 而在编写子程序时, 需要定义一些只在子程序内部使用的变量, 称其为局部变量. 当Maple执行子程序时, 所有和局部变量同名的全局变量都保持不变, 而不管在子程序中给局部变量赋予了何值. 如果要把局部变量定义为全局变量, 需要用关键词global在程序最开始加以声明, 而局部变量则用local声明, 虽然这是不必要的, 但在程序设计时, 声明变量是有一定好处的. 下面通过实例演示局部变量与全局变量的不同. 为了更清楚地观察子程序对全局变量的影响, 在子程序外先设定一个变量a的值:> a:=1;> f:=proc( ) local a; a:=12345678/4321; evalf(a/2);end;> f();> a;> g:=proc( ) global a; a:=12345678/4321; evalf(a/2);end;> g();> a;显然, 在前一个程序中, 由于在子程序外已经赋值给a, a是全局变量, 它的值不受子程序中同名局部变量的影响;而在后一个子程序中, 由于重新把a定义为全局变量, 所以子程序外的a随着子程序中的a值的变化而变化. 子程序中的输入参数, 它既不是全局的, 也不是局部的. 在子程序内部, 它是形式参数, 也就是说, 它的具体取值尚未被确定, 它在程序调用时会被替换成真正的参数值. 而在子程序外部, 它们仅仅表示子程序接受的参数的多少, 而对于具体的参数值没有关系. 1.4 变量nargs, args与procname在所有程序中都有三个有用的变量:nargs, args与procname. 前两个给出关于调用参量的信息: nargs变量是调用的实际参量的个数, args变量是包含参量的表达式序列, args的子序列通过范围或数字的参量选取. 例如, 第i个参量被调用的格式为: args[i]. nargs, args变量通常在含有可选择参量的程序中使用. 下面看一个例子:> p:=proc( )local i;RETURN(nargs,[seq(i^3,i=args)])end proc:> p(1,2,3,4,5,6,7,8,9,10);该程序利用Maple函数RETURN返回了输入参量的个数以及参量序列的立方列表, RETURN函数使用时必须在其后加圆括号,即使无结果返回时也得如此。

      下面是一个关于求任意序列最大值的复杂程序:> maximum:=proc( ) local r, i; r:=args[1]; for i from 2 to nargs do if args[i]>r then r:=args[i] end if end do; r;end proc:> m。

      点击阅读更多内容
      关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
      手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
      ©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.