在线时间 0 小时 最后登录 2012-6-12 注册时间 2012-6-11 听众数 5 收听数 0 能力 0 分 体力 5 点 威望 0 点 阅读权限 10 积分 4 相册 0 日志 0 记录 0 帖子 5 主题 1 精华 0 分享 0 好友 4
升级 80%
该用户从未签到
自我介绍 爱学习
1 W } M' ?( {7 d# ?+ Q4 d {* [
第一章 Maple基础
# S. i; f* a+ k: K; { $ Q/ ^% p) G Z3 Y; _4 e9 Q
1 初识计算机代数系统Maple: S. ]% o% {* e& h
1.1 Maple简说7 k+ h# f8 V% y M: Y9 l
1980年9月, 加拿大Waterloo大学的符号计算机研究小组成立, 开始了符号计算在计算机上实现的研究项目, 数学软件Maple是这个项目的产品. 目前, 这仍是一个正在研究的项目. $ J7 S/ H% ~/ T' n
Maple的第一个商业版本是1985年出版的. 随后几经更新, 到1992年, Windows系统下的Maple 2面世后, Maple被广泛地使用, 得到越来越多的用户. 特别是1994年, Maple 3出版后, 兴起了Maple热. 1996年初, Maple 4问世, 1998年初, Maple 5正式发行. 目前广泛流行的是Maple 7以及2002年5月面市的Maple 8.
$ B W4 B0 ]' \1 i Maple是一个具有强大符号运算能力、数值计算能力、图形处理能力的交互式计算机代数系统(Computer Algebra System). 它可以借助键盘和显示器代替原来的笔和纸进行各种科学计算、数学推理、猜想的证明以及智能化文字处理. ; T2 u4 n0 ?8 B
Maple这个超强数学工具不仅适合数学家、物理学家、工程师, 还适合化学家、生物学家和社会学家, 总之, 它适合于所有需要科学计算的人.
7 a- S" R4 j0 H, h 1.2 Maple结构
1 n) P# y% u- f5 U8 H1 X8 j8 s Maple软件主要由三个部分组成: 用户界面(Iris)、代数运算器(Kernel)、外部函数库(External library). 用户界面和代数运算器是用C语言写成的, 只占整个软件的一小部分, 当系统启动时, 即被装入, 主要负责输入命令和算式的初步处理、显示结果、函数图象的显示等. 代数运算器负责输入的编译、基本的代数运算(如有理数运算、初等代数运算等)以及内存的管理. Maple的大部分数学函数和过程是用Maple自身的语言写成的, 存于外部函数库中. 当一个函数被调用时, 在多数情况下, Maple会自动将该函数的过程调入内存, 一些不常用的函数才需要用户自己调入, 如线性代数包、统计包等, 这使得Maple在资源的利用上具有很大的优势, 只有最有用的东西才留驻内存, 这保证了Maple可以在较小内存的计算机上正常运行. 用户可以查看Maple的非内存函数的源程序, 也可以将自己编的函数、过程加到Maple的程序库中, 或建立自己的函数库. ( q) t9 r# ~* {9 ?
1.3 Maple输入输出方式% l4 Q. _" u `! L5 m/ l0 z
为了满足不同用户的需要, Maple可以更换输入输出格式: 从菜单“Options | Input Display和Out Display下可以选择所需的输入输出格式.
; c# l e3 m- J- i5 j Maple 7有2种输入方式: Maple语言(Maple Notation)和标准数学记法(Standard Math Notation). Maple语言是一种结构良好、方便实用的内建高级语言, 它的语法和Pascal或C有一定程度的相似, 但有很大差别. 它支持多种数据操作命令, 如函数、序列、集合、列表、数组、表, 还包含许多数据操作命令, 如类型检验、选择、组合等. 标准数学记法就是我们常用的数学语言. ; }+ @. \) b$ A& C
启动Maple, 会出现新建文档中的“[>”提示符, 这是Maple中可执行块的标志, 在“>”后即可输入命令, 结束用“;”(显示输出结果)或者“:”(不显示输出结果). 但是, 值得注意的是, 并不是说Maple的每一行只能执行一句命令, 而是在一个完整的可执行块中健入回车之后, Maple会执行当前执行块中所有命令(可以是若干条命令或者是一段程序). 如果要输入的命令很长, 不能在一行输完, 可以换行输入, 此时换行命令用“shift+Enter”组合键, 而在最后一行加入结束标志“;”或“:”, 也可在非末行尾加符号“\”完成.
+ ^5 `( F% k1 c- } l6 U# N Maple 7有4种输出方式: Maple语言、格式化文本(Character Notation)、固定格式记法(Typeset Notation)、标准数学记法(Standard Math Notation). 通常采用标准数学记法.
6 v: u& I* ^& H) | Maple会认识一些输入的变量名称, 如希腊字母等. 为了使用方便, 现将希腊字母表罗列如下,输入时只需录入相应的英文,要输入大写希腊字母, 只需把英文首字母大写:
) i' S- E3 ~! k! U% T3 Z; T3 \ 9 |' H/ v l c+ r/ X8 G. F
; f2 t4 s1 y( I# |
z% }1 l2 _& M% u
2 A4 g! K! a- I; N3 D
5 q, B' g, P7 ~) O
3 M: g$ K: w! x1 }% R
0 |( U0 n# [6 P$ r& f : `. m7 E7 _1 Y4 j- u
7 s$ C# |1 O# |* z
$ V. U! T- _0 o& f( u
% Y7 J! S8 |8 S# x- w$ z8 u% Q ( @0 F1 E+ K; c# V/ a8 Z/ `
# `7 g) d7 B* s% f8 B alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu+ w7 Q, ~% Y; l/ e
, U% ]- C* E2 n4 p5 M . q$ x/ C) _; O9 b. t5 B$ z9 x
* j) P4 I/ S% N) q z
9 ]% r4 `- E& }+ A* Y: O
# S9 x; ?' ~" n- z+ l$ B {
( s; e. S5 _4 D* j
5 z+ I2 Q8 k; f! E, R7 V 2 `& m: c: i* J5 p. X
% t6 I) ]- n- w# z# R5 [7 U
; \2 s+ K. \6 n3 i: O! T . `2 T6 U y0 W5 e0 H6 C4 ]
* t/ F* C3 ^3 d * r6 A3 Q; v3 e# x7 l
nu xi omicron pi rho sigma tau upsilon phi chi psi omega# ~! f5 W" c. P) Z D- H- T& ~
有时候为了美观或特殊需要,可以采用Maple中的函数或程序设计方式控制其输出方式,如下例:
# D* \8 n) U* d% O9 B > for i to 10 do / t3 n# v$ K' h/ |; j k; p& n% J
printf("i=%+2d and i^(1/2)=%+6.3f", i, eval(sqrt(i)));% O7 R6 Y/ ~% U/ k) b. ~. C' _
od;
# o/ c. r* e: ^1 c) k i=+1 and i^(1/2)=+1.000i=+2 and i^(1/2)=+1.414i=+3 and i^(1/2)=+1.732i=+4 and i^(1/2)=+2.000i=+5 and i^(1/2)=+2.236i=+6 and i^(1/2)=+2.449i=+7 and i^(1/2)=+2.646i=+8 and i^(1/2)=+2.828i=+9 and i^(1/2)=+3.000i=+10 and i^(1/2)=+3.162
9 D+ A9 e4 [* Z6 }; r6 W8 ^ +2d的含义是带符号的十进位整数,域宽为2. 显然,这种输出方式不是我们想要的,为了得到更美观的输出效果,在语句中加入换行控制符“\n”即可:+ V9 r* ~* D e' j0 ~* D
> for i to 10 do
) ]* r! P" w9 J9 p/ K6 r7 j printf("i=%+2d and i^(1/2)=%+6.3f\n", i, eval(sqrt(i)));
; i% s. O9 m4 G6 W od;
3 s: ]8 G' c3 B% I, \. H. H7 F i=+1 and i^(1/2)=+1.0008 n7 i, ?$ p) y, V: B, E' `
i=+2 and i^(1/2)=+1.4141 d! Q) I( `, J7 j
i=+3 and i^(1/2)=+1.732
0 I) I5 r- q& a! l$ @+ o) I i=+4 and i^(1/2)=+2.000
, E9 i# A$ T4 h9 O3 b i=+5 and i^(1/2)=+2.236
3 R/ O, @/ H" H7 D0 f- L i=+6 and i^(1/2)=+2.449
, Z& _* e8 o& z: I& @4 c; M6 j i=+7 and i^(1/2)=+2.646/ {, @# l7 d) W5 M5 [- j
i=+8 and i^(1/2)=+2.828$ b' Q( P O& L8 H1 N
i=+9 and i^(1/2)=+3.0007 _. V2 w4 q" K9 G; a
i=+10 and i^(1/2)=+3.162, ]# s8 Q+ x* v# i
再看下例:将输入的两个数字用特殊形式打印:, B/ D! E6 g4 E9 R7 ?
> niceP:=proc(x,y)
9 n s- |: ^' f! L1 Y printf("value of x=%6.4f, value of y=%6.4f",x,y);
7 v5 P$ Y. g$ Q, z end proc;
* `& ^3 r N4 i' m& B $ ^" o, {% T. f* A+ F6 y
> niceP(2.4,2002.204);
$ ~& X, m; H, }- _3 T" G. P. z value of x=2.4000, value of y=2002.2040+ |. a/ \( S; b9 g8 a- K
1.4 Maple联机帮助
8 k8 G" p( d* u3 B: B 学会寻求联机帮助是掌握一个软件的钥匙. Maple有一个非常好的联机帮助系统, 它包含了90%以上命令的使用说明. 要了解Maple的功能可用菜单帮助“Help”, 它给出Maple内容的浏览表, 这是一种树结构的目录表, 跟有…的词条说明其后还有子目录, 点击这样的词条后子目录就会出现(也可以用Tab键和up, down选定). 可以从底栏中看到函数命令全称, 例如, 我们选graphics…, 出现该条的子目录, 从中选2D…, 再选plot就可得到作函数图象的命令plot的完整帮助信息. 一般帮助信息都有实例, 我们可以将实例中的命令部分拷贝到作业面进行计算、演示, 由此可了解该命令的作用. % [! w p* F" @% U, J
在使用过程中, 如果对一个命令把握不准, 可用键盘命令对某个命令进行查询. 例如, 在命令区输入命令“?plot”(或help(plot);), 然后回车将给出plot命令的帮助信息, 或者将鼠标放在选定的要查询的命令的任何位置再点击菜单中的“Help”即可. 6 w+ b/ O8 l% V- R3 I
2 Maple的基本运算: B8 _- |2 `/ H
2.1 数值计算问题/ {. c( L$ Z; ^
算术是数学中最古老、最基础和最初等的一个分支, 它研究数的性质及其运算, 主要包括自然数、分数、小数的性质以及他们的加、减、乘、除四则运算. 在应用Maple做算术运算时, 只需将Maple当作一个“计算器”使用, 所不同的是命令结束时需加“;”或“:”. 8 o- E& Z! i0 Q1 K. v3 X
在Maple中, 主要的算术运算符有“+”(加)、“–”(减)、“*”(乘)、“/”(除)以及“^”(乘方或幂,或记为**), 算术运算符与数字或字母一起组成任意表达式, 但其中“+”、“*”是最基本的运算, 其余运算均可归诸于求和或乘积形式. 算述表达式运算的次序为: 从左到右, 圆括号最先, 幂运算优先, 其次是乘除,最后是加减. 值得注意的是, “^”的表达式只能有两个操作数, 换言之, 是错误的, 而“+”或“*”的任意表达式可以有两个或者两个以上的操作数.
9 v/ ^. e3 l! Q( m Maple有能力精确计算任意位的整数、有理数或者实数、复数的四则运算, 以及模算术、硬件浮点数和任意精度的浮点数甚至于矩阵的计算等等. 总之, Maple可以进行任意数值计算. : s& w# |: B- Y" D# R0 t* H
但是, 任何软件或程序毕竟只是人们进行科学研究的一种必要的辅助, 即便它有很多优点, 但也有它的局限性, 为了客观地认识数学软件、认识Maple, 下面通过两个简单例子予以说明. 7 Q/ n9 v, y5 a, _3 H3 i
第一个简单的数值计算实例想说明Maple数值计算的答案的正确性:
0 w2 Y2 R* V& f* @! Z) {# u8 {: { > 3!!!;+ d" u8 P: ?; F$ B/ |5 w2 U2 W* j) h
2601218943565795100204903227081043611191521875016945785727541837850835631156947382240678577958130457082619920575892247259536641565162052015873791984587740832529105244690388811884123764341191951045505346658616243271940197113909845536727278537099345629855586719369774070003700430783758997420676784016967207846280629229032107161669867260548988445514257193985499448939594496064045132362140265986193073249369770477606067680670176491669403034819961881455625195592566918830825514942947596537274845624628824234526597789737740896466553992435928786212515967483220976029505696699927284670563747137533019248313587076125412683415860129447566011455420749589952563543068288634631084965650682771552996256790845235702552186222358130016700834523443236821935793184701956510729781804354173890560727428048583995919729021726612291298420516067579036232337699453964191475175567557695392233803056825308599977441675784352815913461340394604901269542028838347101363733824484506660093348484440711931292537694657354337375724772230181534032647177531984537341478674327048457983786618703257405938924215709695994630557521063203263493209220738320923356309923267504401701760572026010829288042335606643089888710297380797578013056049576342838683057190662205291174822510536697756603029574043387983471518552602805333866357139101046336419769097397432285994219837046979109956303389604675889865795711176566670039156748153115943980043625399399731203066490601325311304719028898491856203766669164468791125249193754425845895000311561682974304641142538074897281723375955380661719801404677935614793635266265683339509760000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000+ s6 C; o- T2 J
上述运算结果在IBM PC机(1G, 128M)上计算只需要0.01秒, 得到如此复杂的结果(1747位), 一个自然的问题是: 答案正确吗?
4 C7 S- E' u# Z 为了回答这个问题, 我们借助于数值分析方法, 由Stiring公式
* l6 y7 h! {( ]3 _
d9 r0 J1 x/ Y8 `% l3 I9 ` 可得: , 前三位数字与Maple输出结果相同, 且两者结果均为1747位. 另外, 在720!的计算中, 5的因子的个数为:
2 Y) t) ]6 D' ?) m 1 F( `8 i$ T. F4 i" F8 h
这些5与足够多的2相乘将得到178个0, 而Maple的输出结果中最后178位数为零. 由此, 可以相信Maple结果的正确性. 4 R0 [# r# Q2 F+ F* ~* l4 G
另一个例子则想说明Maple计算的局限性: ( {3 r4 ]; y5 N# ]: V8 t$ ^! d
/ N: w6 _7 H6 _* k
Maple在处理问题时, 为了避免失根, 从不求算术式的近似值, 分数则化简为既约分数. 因此, 在Maple中很容易得到:
8 c% E' _( S7 q
( l: N4 e# D; q# W 显然这是错误的. 这一点可以从代数的角度予以分析. - n. ?( }0 G; v y. y" n+ @; ~
不妨设 , 则 , 即 , 显然 有3个结果, -2是其实数结果. k, F" G+ E7 s% }, F
另一方面, 设 , 则 , 即:) ?& T. v9 Q8 g
& W' [7 I1 {) h8 L5 {9 u0 k1 R 显然 有6个结果, -2、2是其实数结果.
; Z" [% J; S0 z 这个简单的例子说明了Maple在数值计算方面绝对不是万能的, 其计算结果也不是完全正确的, 但是, 通过更多的实验可以发现: Maple只可能丢失部分结果, 而不会增加或很少给出完全错误的结果(如上例中Maple的浮点数结果皆为 ). 这一点提醒我们, 在利用Maple或其他任何数学软件或应用程序进行科学计算时, 必须运用相关数学基础知识校验结果的正确性. 2 T& \" \# V( M1 S; ^
尽管Maple存在缺陷(实际上, 任何一个数学软件或程序都存在缺陷), 但无数的事实说明Maple仍然不失为一个具有强大科学计算功能的计算机代数系统. 事实上, Maple同其他数学软件或程序一样只是科学计算的一个辅助工具, 数学基础才是数学科学中最重要的. 4 r) p, i( t, b
2.1.1 有理数运算
$ J( f i: k( S% n2 Y& y 作为一个符号代数系统, Maple可以绝对避免算术运算的舍入误差. 与计算器不同, Maple从来不自作主张把算术式近似成浮点数, 而只是把两个有公因数的整数的商作化简处理. 如果要求出两个整数运算的近似值时, 只需在任意一个整数后加“.”(或“.0”), 或者利用“evalf”命令把表达式转换成浮点形式, 默认浮点数位是10 (即: Digits:=10, 据此可任意改变浮点数位, 如Digits:=20). - K R/ D3 l; C$ o4 s
> 12!+(7*8^2)-12345/125;
- t |9 h J U% a- [1 o! g2 l6 U% L% G( U
) R) S# }: [) p& ? > 123456789/987654321;8 Q' B* ]; C0 t; q# h8 o
7 u. }# ^+ n. b* Y5 P > evalf(%); r8 z" N/ S, @. v( ~
+ W1 L$ D( W. V" b3 I
> 10!; 100*100+1000+10+1; (100+100)*100-9;! V4 h! X; h, a8 d* E8 i) j8 F
, z3 `9 W0 b5 r0 e5 V V3 i1 r
8 V2 r4 `2 t# L# ^2 o
m& _: [) a5 M' m2 g > big_number:=3^(3^3);$ }* q- {0 _ s" g7 k1 ?
" v( o1 p8 l, w. k% u
> length(%);7 r" u/ ]9 _! K/ C. |3 m. F
9 s; Y3 a0 G/ _/ f% u- ~5 S 上述实验中使用了一个变量“big_number”并用“:=”对其赋值, 与Pascal语言一样为一个变量赋值用的是“:=”. 而另一个函数“length”作用在整数上时是整数的十进制位数即数字的长度. “%”是一个非常有用的简写形式, 表示最后一次执行结果, 在本例中是上一行输出结果. 再看下面数值计算例子:
$ X0 X" F" b; r 1)整数的余(irem)/商(iquo)
! m2 W0 Z) k: ]; k 命令格式:
1 j5 ^/ X: l5 [& N. ] irem(m,n); #求m除以n的余数
5 k/ H7 F; B. Y. c g6 C' {: s irem(m,n,'q'); #求m除以n的余数, 并将商赋给q* P4 G% }$ Y- Z" P% G7 [
iquo(m,n); #求m除以n的商数
; }/ R/ h! \. w3 S4 w& |6 h& F: V iquo(m,n,'r'); #求m除以n的商数, 并将余数赋给r2 ^) E, F1 B) Y$ }' R2 w
其中, m, n是整数或整数函数, 也可以是代数值, 此时, irem保留为未求值.
P) R8 A* ^" D/ ? > irem(2002,101,'q'); # 求2002除以101的余数, 将商赋给q+ X- ], u3 g8 {' K5 t, u
% g6 @( L& ]8 l/ k, |. G9 A
> q; #显示q
8 B0 O- c/ C- t) t" X" i. u 0 _# v! i6 r, [; X
> iquo(2002,101,'r'); # 求2002除以101的商, 将余数赋给r( Q A# Y9 \( P& {' R
x0 q$ o. j# j0 v2 [# S! h > r; #显示r4 l% l3 t$ J \" z& `2 N
* m) h2 N; c# K, o. `# I6 L
> irem(x,3);
& N. p$ Q" U4 G : B$ i0 r* U x8 O
2)素数判别(isprime)
: \9 ~( u; }$ K& r7 _5 _- G 素数判别一直是初等数论的一个难点, 也是整数分解问题的基础. Maple提供的isprime命令可以判定一个整数n是否为素数. 命令格式: isprime(n); # d" _$ n; L4 T! ]! z( V1 B: d
如果判定n可分解, 则返回false, 如果返回true, 则n“很可能”是素数. ( u! f, |. z: t6 U& k
> isprime(2^(2^4)+1);
6 p" }* L/ p" t7 @; M6 `$ {
* G$ O) B! v2 Z9 \ > isprime(2^(2^5)+1);' f4 A3 m j' V1 R' f; Q
( e8 K- B8 x. a/ \ 上述两个例子是一个有趣的数论难题。形如 的数称为Fermat数, 其中的素数称为Fermat素数, 显然, F0=3、F1=5、F2=17、F3=257、F4=65537都是素数. Fermat曾经猜想所有的Fn都是素数, 但是Euler在1732年证明了F5=641•6700417不是素数. 目前, 这仍是一个未解决的问题, 人们不知道还有没有Fermat素数, 更不知道这样的素数是否有无穷多. 8 @, V( b$ n# p% ^
3) 确定第i个素数(ithprime)
/ Q# `- J: g! d2 _. e1 ] 若记第1个素数为2,判断第i个素数的命令格式: ithprime(i); , I5 N& L. \) ~. G, T) B) H
> ithprime(2002);' [- i/ f; ~; J4 \7 {$ F
' E( C2 N! Z+ q+ l- u$ c) w; [* l: f
> ithprime(10000);1 }$ ^6 f& m- ?4 |
, F+ D. \( y( q9 n
4) 确定下一个较大(nextprime)/较小(prevprime)素数( k) B# V" b5 }; N' x
当n为整数时,判断比n稍大或稍小的素数的命令格式为: 9 v9 H% F4 K' d" `3 x! I
nextprime(n); 2 R7 F2 Y0 D% i) p! B7 J% t) j6 t
prevprime(n); ' A/ w1 U, c* u
> nextprime(2002);
' B; _/ a9 `" o. Y3 |! p8 u. c 3 x* W' _, O8 o! }
> prevprime(2002);
9 I6 p4 I4 k, Z4 G3 q8 z* ?
2 a! G/ ]+ U2 j. Y" a 5) 一组数的最大值(max)/最小值(min)& x* ]. m& M) R
命令格式: max(x1,x2,…,xn); #求x1,x2,…,xn中的最大值
: X% w5 N) x8 E2 I' b min(x1,x2,…,xn); #求x1,x2,…,xn中的最小值
* X- o- s+ g( w. h; J- s > max(1/5,ln(3),9/17,-infinity);
5 w$ K$ G: t- r / f# r D; F1 o. }4 j9 I- z8 u
> min(x+1,x+2,y);
1 D, e, n( r0 P8 `8 |5 d 4 c; ~9 L8 {. h7 H
6)模运算(mod/modp/mods)5 [* T( O1 C9 B
命令格式: e mod m; # 表达式e对m的整数的模运算" Z9 U) ]: k* U
modp(e,m); # e对正数m的模运算
2 u' Z$ |* j& K5 ?/ c6 N+ {0 F" J mods(e,m); # e对m负对称数(即 -m)的模运算) M7 p: |+ q8 X
`mod`(e,m); # 表达式e对m的整数的模运算, 与e mod m等价8 u7 c( u5 K' y9 l8 Z0 }
值得注意的是, 要计算i^n mod m(其中i是一整数), 使用这种“明显的”语法是不必要的, 因为在计算模m之前, 指数要先在整数(可能导致一个非常大的整数)上计算. 更适合的是使用惰性运算符“&^”即: i &^n mod m, 此时, 指数运算将由mod运算符智能地处理. 另一方面, mod运算符的左面优先比其他运算符低, 而右面优先高于+和-, 但低于*和/.
7 N/ e9 k% {, G+ u6 w- o) w$ r > 2002 mod 101;8 d; l; \0 ^6 R8 r3 U- _7 R" r
% P3 [0 W7 [5 r/ E: T: Q8 j8 e > modp(2002,101);0 c3 a/ q- E- c3 v3 p) f
# P' m% }3 m2 w$ {8 t > mods(49,100);. s/ P& n2 v4 ^' {) F; d
! d! c5 {* Y/ w- n9 ]0 s2 t
> mods(51,100);
5 ~9 E. _9 C, K2 a( @+ F, Q
4 O% ?! F% ^9 C9 [( B > 2^101 mod 2002; # 同 2 &^101 mod 2002;8 O5 S+ |. b8 A
: v. C L8 k5 H+ V3 r
7)随机数生成器(rand)
8 M6 _; ]; X F 命令格式:
7 E* g% T# W3 _9 L3 [- W3 W& o rand( ); #随机返回一个12位数字的非负整数: j# m' E+ }( i+ ]9 a9 Q8 x3 B
rand(a..b); #调用rand(a..b)返回一个程序, 它在调用时生成一个在范围[a, b]内的随机数
# I H" G6 f! H* h# i# ^+ S4 j > rand();
) |5 A! ^- x- q
# j& U/ ~1 _2 }" G > myproc:=rand(1..2002):
# A3 I8 x# a# g, c9 d4 z! P; y; ~& V# B > myproc();
+ p4 I# J1 C' K1 s9 }4 \8 H: t
* |5 @- r1 S5 ]4 d$ @ > myproc();
& J$ l; g# i0 w% l6 q 3 J- T! I9 f( u# s
注意, rand(n)是rand(0..n-1)的简写形式.
; |4 `8 p; D6 s5 i% A 2.1.2 复数运算
* ]8 K Z4 K- O. }0 U& d 复数是Maple中的基本数据类型. 虚数单位i在Maple中用I表示. 在运算中, 数值类型转化成复数类型是自动的, 所有的算术运算符对复数类型均适用. 另外还可以用Re( )、Im( )、conjugate( )和argument( )等函数分别计算实数的实部、虚部、共轭复数和幅角主值等运算. 试作如下实验: 6 k$ `# w8 f* U. R) G
> complex_number:=(1+2*I)*(3+4*I);
! @& e8 }! Y9 ~, k, e9 r" e0 `" O/ n
" \$ n" g8 ~ q s2 V& e; d > Re(%);Im(%%);conjugate(%%%);argument(complex_number);" L3 Y8 R( ^3 `4 |2 x
/ Q/ k2 V" O2 B) ~5 m. q
* ]) b: d- Z' Y& m5 \& F- X
3 g" P4 j! z: H3 }/ X: r8 M
: Y5 u+ T' n" a E9 M7 Q# D 值得注意的是上行命令中均以“;”结束, 因此不能将命令中的2个%或3个%(最多只能用3个%)改为1个%, 因为%表示上一次输出结果, 若上行命令改为“,”结束, 则均可用1个%.
: w. X. L4 J Q( p( i. T& K 为了在符号表达式中进行复数运算, 可以用函数evalc( ), 函数evalc把表达式中所有的符号变量都当成实数, 也就是认为所有的复变量都写成 的形式, 其中a、b都是实变量. 另外还有一些实用命令, 分述如下:
. t ^: T" p# s. o 1) 绝对值函数3 e" P: E" N/ A5 D V- {. f/ W
命令格式: abs(expr);
: ], `- Z7 a# O: i p# h2 p 当expr为实数时,返回其绝对值,当expr为复数时,返回复数的模.
0 Z8 i' d4 X$ V4 l. I' y > abs(-2002); #常数的绝对值& a1 R R/ k. k, D+ I
' {' e3 T% S+ U8 x, N9 X6 s
> abs(1+2*I); #复数的模
" ]9 h; z- t& P/ ?9 P
J7 p4 o( r! L; @ > abs(sqrt(3)*I*u^2*v); #复数表达式的绝对值# ]( Z; E" d# i) }1 P3 z% T+ Y
8 ~4 } f+ E; h0 C. _
> abs(2*x-5); #函数表达式的绝对值9 p7 E5 h4 }3 ^$ x# X2 w j
; p! n8 t8 Y' ] j
2)复数的幅角函数$ f- Y3 k7 M, ?) v$ Z
命令格式: argument(x); #返回复数x的幅角的主值
& s$ Z7 o. v8 w > argument(6+11*I);
4 }1 N6 c$ L- ^1 e! z8 D% V, q
1 U: u/ @0 Q8 q3 ]/ J/ b. i) \ > argument(exp(4*Pi/3*I));
4 X/ ^- T0 e5 X1 C+ m6 F* B m$ S % u Y ?5 O4 V5 ?4 p
3)共轭复数
. X; m3 y; i( \! J" r# g0 k' ` 命令格式: conjugate(x); #返回x的共轭复数
, w$ Z/ L* h' E. \+ e > conjugate(6+8*I);! Y3 {0 x, D9 N2 {- y
) s- I$ v& `! i; R# k > conjugate(exp(4*Pi/3*I));3 X! K& v# p7 V8 J: i9 V
1 V+ |8 q3 V6 M
2.1.3 数的进制转换# O3 W/ b1 P( x' ?% o
数的进制是数值运算中的一个重要问题. 而在Maple中数的进制转换非常容易, 使用convert命令即可.
8 d2 s+ A) k" b9 Q2 ` 命令格式: convert(expr, form, arg3, ...);
$ }2 J; T2 R A6 D) S 其中, expr为任意表达式, form为一名称, arg3, ... 可选项. 1 s. i( N- g6 j6 H9 ~% d
下面对其中常用数的转换予以概述. 而convert的其它功能将在后叙章节详述.
. X* ?1 w! q/ S: |) N' K 1)基数之间的转换
3 O: {" ?* c4 ^2 ~$ b 命令格式: ; @( B( P1 J9 B0 P# F* Y0 C
convert(n, base, beta); #将基数为10的数n转换为基数为beta的数
! I& T4 c' ]2 S6 H convert(n, base, alpha, beta);#将基数为alpha的数字n转换为基数为beta的数
: L' ?* ?2 @% |/ N$ p* R" j > convert(2003,base,7); #将10进制数2002转换为7进制数, 结果为: (5561)7
2 B3 j8 h/ O0 _# @
" L5 o& S2 ^! [/ g* c: w > convert([1,6,5,5],base,7,10); #将7进制数5561转换为10进制数! x( ^5 P+ {; o6 d" Q
4 h5 \* U) Q5 y$ e' G: T) w/ @) h > convert(2002,base,60); #将十进制数2002转换为60进制数, 得33(分钟)22(秒)+ B9 b8 [* h' ?& V
, t6 S. D* [+ }- M) j! c/ t5 h8 \ 2)转换为二进制形式
- @8 B7 K @' s$ A- S 命令格式: convert(n, binary);2 u6 Z# b; @6 K
其功能是将十进制数n转换为2进制数. 值得注意的是, 数可以是正的, 也可以是负的, 或者是整数, 或者是浮点数, 是浮点数时情况较为复杂.
0 |, ?6 T) \4 o0 \: N9 T4 | ^ > convert(2002,binary);
+ ^7 d8 J) u$ L, X
0 A3 y. D' [: j" f, \) B+ S > convert(-1999,binary); 1 y% l2 V2 ~9 W& A& K6 Q/ A5 c
- w4 l0 D1 K5 }6 y. Y( H9 s
> convert(1999.7,binary);
0 n# n0 l3 ~! t8 r% S' z6 F ' {% l7 z! ?5 A/ d: [5 m- J
3)转换为十进制形式
4 L2 Y1 N$ P4 l6 U& s$ [, s 其它数值转换为十进制的命令格式为: , X8 Y' x5 T& {; N3 h$ a. [% J2 u1 m4 _
convert(n, decimal, binary); #将一个2进制数n转换为10进制数
4 q7 q) d$ e$ c2 y5 x convert(n, decimal, octal); #将一个8进制数n转换为10进制数4 Q9 p. j F4 B1 }
convert(string, decimal, hex); #将一个16进制字符串string转换为10进制数
7 X3 |7 J( B9 M& I5 f# D > convert(11111010010, decimal, binary);
9 T9 L }( ?' j ' {" ?. v G% S! `$ K; j7 A/ V
> convert(-1234, decimal, octal); 4 T- R3 w7 \! p- s J
# Z5 r3 w5 s S3 V$ p
> convert("2A.C", decimal, hex); : x" c4 R. E9 s$ G# t/ G0 q
' a& a! F) Y) }$ y; ]
4) 转换为16进制数: K; J1 L5 _- g+ d
将自然数n转换为16进制数的命令格式为: convert(n, hex); 7 ^& j3 o4 O% W4 I: W
> convert(2002,hex); convert(1999,hex);
0 ~* z V/ e9 _3 o" t: G2 O
# c7 f6 l k+ n( K
" D& e9 f3 u# q3 z 5)转换为浮点数
7 W. p) ?5 K2 J) M3 P* T8 I 命令格式: convert(expr, float);
* I( g# X, k3 R 注意, convert/float命令将任意表达式转换为精度为全局变量Digits的浮点数, 且仅是对evalf的调用. . n, K( k$ t; ?4 }* M( E
> convert(1999/2002,float);7 x8 H1 n; Z, k! N8 G2 P8 M% j
+ U) y- P% n7 G$ _8 @% o0 a
> convert(Pi,float);
4 N3 b0 E8 a6 D9 [2 B' M 1 S4 R: g" B' L' ^& I
2.2 初等数学
8 P$ n- V4 R% l, v$ z, n. [ 初等数学是数学的基础之一, 也是数学中最有魅力的一部分内容. 通过下面的内容我们可以领略Maple对初等数学的驾驭能力, 也可以通过这些实验对Maple产生一些感性认识. 7 g: S% o; b8 {. H# v6 h) Z
2.2.1 常用函数
4 P" y7 F; W" J& R/ p8 O( p; f 作为一个数学工具, 基本的数学函数是必不可少的, Maple中的数学函数很多, 现例举一二如下:
9 x' d+ b j6 ~/ F 指数函数: exp
$ q4 u" n" s& k# b 一般对数: log[a]
/ Y: J( Y9 _* u! k E 自然函数: ln
9 `. X! O \9 S8 }, u 常用对数: log104 ]0 L. n! [) Q* t0 q: t
平方根: sqrt$ M5 ?" j; n* S( ^! ?
绝对值: abs
4 I6 ]1 Y* T! T 三角函数: sin、cos、tan、sec、csc、cot
: {/ q- B+ ?/ Q% o* k0 y 反三角函数: arcsin、arccos、arctan、arcsec、arccsc、arccot4 G; t$ x& ?7 M
双曲函数: sinh、cosh、tanh、sech、csch、coth5 | |: V; W% P5 o* `% j# I
反双曲函数: arcsinh、arccosh、arctanh、arcsech、arccsch、arccoth
; t6 }2 r: w8 p7 Z 贝赛尔函数: BesselI、BesselJ、BesselK、BesselY8 ]7 H: F V, b0 N b) n( y6 ^9 `
Gamma函数: GAMMA
2 B+ F# f1 t/ f) [5 }, C& r+ f% a( W/ ~ 误差函数: erf
& b' w: o; {8 u) p9 k! L6 _/ {6 M 函数是数学研究与应用的基础之一, 现通过一些实验说明Maple中的函数的用法及功能.
9 _3 o$ \$ p7 E& d- g. F 1) 确定乘积和不确定乘积8 }% w; c6 u& o/ p: J: _
命令格式: product(f,k); * k L5 i1 V6 \+ m0 W
product(f,k=m..n); 7 f7 ?: h. N- R. s3 U$ t# r& ^
product(f,k=alpha); * ^, h* Y( T) Z* y) w$ m9 W+ f4 h
product(f,k=expr);
) M6 p5 m3 L; y W e' g! @ 其中, f—任意表达式, k—乘积指数名称, m,n—整数或任意表达式, alpha—代数数RootOf, expr—包含k的任意表达式. % A0 T2 m6 K1 v9 Y7 `
> product(k^2,k=1..10); #计算 关于1..10的连乘3 v# _2 \% o; a% n# K: u
1 Y7 p) |) Y$ U) z) w# H; |: t
> product(k^2,k); #计算 的不确定乘积
4 v% J$ q% f2 Q& O- d
% t& n( A1 Z9 q7 h) P# K" U* q0 q7 N) h > product(a[k],k=0..5); #计算ai(i=0..5)的连乘
" G/ g$ c! u! F5 j) U& [: a
2 r2 S* t7 S; F > product(a[k],k=0..n); #计算ai(i=0..n)的连乘
4 A) M: v& T2 P- w% F* M 8 O. D c- d, D( z& U
> Product(n+k,k=0..m)=product(n+k,k=0..m); #计算(n+k)的连乘, 并写出其惰性表达式0 N- ]2 E% _ f. g) q6 g
" T7 `0 p7 i, ]; S > product(k,k=RootOf(x^3-2)); #计算 的三个根的乘积' `7 \# x W; z/ i8 y x* l
' a! f# y8 I) M9 j* q product命令计算符号乘积, 常常用来计算一个公式的确实或不确实的乘积. 如果这个公式不能求值计算, Maple返回 函数. 典型的例子是:
+ O1 I& K H1 j7 R9 J5 N > product(x+k,k=0..n-1);
4 U9 @; T6 C, Y# B9 c
/ t9 j4 F, j; O, j6 Z; j# B4 Z 如果求一个有限序列值的乘积而不是计算一个公式, 则用mul命令. 如: o; P7 w2 E8 i( \3 E8 t7 [
> mul(x+k,k=0..3);
* N7 a! l& {: L 2 D4 T& Z% {4 ^4 w5 A
2)指数函数
, B' x' P/ v" @( \: C% R 计算指数函数exp关于x的表达式的命令格式为: exp(x);
1 M- v: l3 h) @2 E+ S$ h > exp(1);
2 t2 i9 h0 a6 q! P3 A ' q/ E% b7 |# t" g) b u9 H+ u/ X
> evalf(%);
" M/ W. A! D: t4 x0 J0 `; s & [/ [6 V4 E6 t2 x
> exp(1.29+2*I);
7 x' h) G6 r( u1 S ; D2 e) `3 F6 Y. u2 I; Q( A: _
> evalc(exp(x+I*y));
4 q7 x5 C% Z* q1 G5 {
% A2 j$ U5 n6 l7 P! H 3)确定求和与不确定求和sum
' |/ ^6 I+ V3 a% P1 ~2 H' o- C0 C 命令格式: sum(f,k); 4 `3 j: W+ u. B ?4 D$ ]# K
sum(f,k=m..n); 9 z# ?6 H1 ^# |7 D+ f# |* Z
sum(f,k=alpha);
, O7 A7 B$ m% s3 ] sum(f,k=expr);# t1 Z+ @ z; Q6 N! i% U
其中, f—任意表达式, k—乘积指数名称, m,n—整数或任意表达式, alpha—代数数RootOf, expr—不含k的表达式.
- }$ C) ~! S: l" W > Sum(k^2,k=1..n)=sum(k^2,k=1..n);3 n% ]: I5 Y) U! t& Q4 ` ^
. V* A3 O1 _2 l
> Sum(k^3,k=1..n)=sum(k^3,k=1..n);7 Y3 b6 [) `! W; Q4 L
& ]8 p& x: F$ f# O1 o. L* N& P
> Sum(k^4,k=1..n)=sum(k^4,k=1..n);2 L4 }1 F) k; j' p- m4 p
! v$ c9 T% P8 K0 i6 |$ `2 V > Sum(1/k!,k=0..infinity)=sum(1/k!,k=0..infinity);
5 a4 ~ Y& n# j$ ]0 V
" z* m, k2 D8 N- z6 n > sum(a[k]*x[k],k=0..n);
* N( i T% E" Q R$ I % h$ W2 g: O6 K* l0 Z
> Sum(k/(k+1),k)=sum(k/(k+1),k);; g& o# m( V" F
% [. U- G; U9 t; M3 ^
> sum(k/(k+1),k=RootOf(x^2-3));
8 w, p9 J3 `) l" E8 W 3 T2 t% u: g+ a- U
sum函数可计算一个公式的确定和与不确定和, 如果Maple无法计算封闭形式, 则返回未求值的结果. 值得注意的是, 在sum命令中将f和k用单引号括起来, 可避免过早求值. 这一点在某些情况下是必需的.
+ C% q! Q3 F. `( {- q9 b6 |) j > Sum('k','k'=0..n)=sum('k','k'=0..n);
- K* K1 I$ p: p N
0 I7 j0 N0 }) b% R; h 如果计算一个有限序列的值, 而不是计算一个公式, 可用add命令. 如: _+ G; U) k( a2 c. v( }
> add(k,k=1..100);+ F J C& G4 ]! G7 s9 T
5 B" t" v O5 d; j+ V& S/ U7 } 尽管sum命令常常用于计算显式求和, 但在程序设计中计算一个显式和应该使用add命令.
( g8 r/ _( i0 T ` 另外, sum知道各种求和方法, 并会对各类发散的求和给出正确的结果, 如果要将求和限制为收敛求和, 就必须检查显式的收敛性. & @- h% e4 l" o' w& _* A
3)三角函数/双曲函数
$ P; l3 K8 p) U; J 命令格式: sin(x); cos(x); tan(x); cot(x); sec(x); csc(x);* U. }# R. g. w) V* V+ z, v# S5 G
sinh(x); cosh(x); tanh(x); coth(x); sech(x); csch(x);
0 T, `) U2 m3 d# f+ I 其中, x为任意表达式. & t6 \ e* o& ^. W5 h
值得注意的是三角函数/双曲函数的参数以弧度为单位. Maple提供了利用常见三角函数/双曲函数恒等式进行化简和展开的程序, 也有将其转化为其它函数的命令convert.1 A, P* A) \9 h f$ ^- E
> Sin(Pi)=sin(Pi);
& I7 a3 G2 c! z" e0 \4 h
( J6 }# f3 `# \) l/ u > coth(1.9+2.1*I);
9 u6 k4 t% E6 \3 L8 K5 S+ i( o4 M" e, ^ & l A9 V$ U: Q, ~7 v
> expand(sin(x+y)); #展开表达式9 B0 V7 q8 A# x& o" \5 Z c
J4 n1 P" u; |8 Y > combine(%); #合并表达式
8 Z" h- [5 `2 \& O& }/ T# n
/ `( w, p7 z3 ?% ~: y1 Q7 { > convert(sin(7*Pi/60),'radical');
8 @( z& m9 @0 m0 Z" Q
8 S8 f1 o# M1 D* |* S: p0 b7 }" e > evalf(%);& y6 P+ D* E* q, B" g$ h0 n4 S( G
% P/ v. I/ E( q( V( \9 l
但有趣的是, combine只对sin, cos有效, 对tan, cot竟无能为力.
# @0 l; |7 n2 i, k: b" T2 z: p 4)反三角函数/反双曲函数
) X/ S& u d1 O# g# m7 Q 命令格式: arcsin(x); arccos(x); arctan(x); arccot(x); arcsec(x); arccsc(x);0 Y) \9 r7 @& A- q# y6 T6 t
arcsinh(x); arccosh(x); arctanh(x); arccoth(x); arcsech(x); arccsch(x); 9 Q9 \. D. M1 C- {' b; K$ `
arctan(y,x);
, P+ J" l: U) J: @. u' j/ r 其中, x, y为表达式. 反三角函数/反双曲函数的参数必须按弧度计算. 3 q- Z, q) X5 _( u
算子记法可用于对于反三角函数和反双曲函数. 例如, sin@@(-1)求值为arcsin.( [% s% u; ?4 m8 z
> arcsinh(1);
( A; l" A: C" p3 ]1 t& L& x
7 p% C/ }& t( H8 ]: C > cos(arcsin(x));) n0 E( ~2 q$ c' n
: W" o( V1 t! |4 o& m3 l
> arcsin(1.9+2.1*I); W2 L# L2 o0 c. p9 J
* ~# I' I* n, ^
5)对数函数
) V; ~* I2 M/ C1 r! M; S; J7 n; {2 b 命令格式: ln(x); #自然对数
8 i2 ^+ B0 K ^- t- v+ y) I log[a](x); #一般对数1 M% n( \& E T. ~" a% N
log10(x); #常用对数- ^& e" e* X9 z8 v% H0 [( M) O4 v
一般地, 在ln(x)中要求x>0. 但对于复数型表达式x, 有: ' {' |, c( t! ]% S
(其中, )5 E/ I4 M6 _5 T( {( j: ]2 \1 m
> ln(2002.0);
) Q/ t- K3 e3 T6 N" D5 C ' |' V) Q/ R0 a/ s4 `
> ln(3+4*I);5 D" C' {5 y1 H7 [& g9 @9 X9 H
5 _* C. _' T0 d. Y
> evalc(%); # 求出上式的实部、虚部
4 t3 I. W8 O, K& k # B# [3 T0 `8 h/ q* ~4 r
> log10(1000000);
5 e/ H/ U+ f+ Z0 G! t3 N
! ]# L' b! B3 ~ > simplify(%); #化简上式% e) J& }7 k$ {$ ?. |6 V
$ s( ?& y, ?9 K7 }* ?6 f. _" L 2.2.2 函数的定义: j' j: r" T! M+ _1 b0 `
Maple是一个计算机代数系统, 带未知或者已知字母变量的表达式是它的基本数据形式. 一个简单的问题是, 既然表达式中可以包含未知变量, 那么它是不是函数呢?试看下面一个例子: 2 n. j: h1 p: J' p! n; x
> f(x):=a*x^2+b*x+c;$ }* A4 C6 _( H+ t
" \, Z& Q; e6 }# T8 q" d' R
可以看出, Maple接受了这样的赋值语句, 但f(x)是不是一个函数呢?要回答这个问题,一个简单的方法是求函数值:
4 { M5 [7 p% P0 E: V& c. G > f(x),f(0),f(1/a);2 s, P; t/ n9 \1 G
2 b3 u1 w( n& ]. {
由上述结果可以看出, 用赋值方法定义的f(x)是一个表达式而不是一个函数, 因为f(x)不能把所定义的“自变量”或者“参数”转换成别的变量或表达式. 但从赋值“过程”可以看出, f(x)虽然也算是一个“函数”, 但却是一个没有具体定义的函数: 5 c; Q, ~8 y0 ?5 Q5 x( k3 {) X
> print(f);
8 D+ R, a* \0 w2 c$ S8 O
7 L# N( O0 W7 } \: V 事实上, 我们所做的赋值运算, 只不过是在函数f的记忆表(remember table)中加入了f(x)在x上的值, 当我们把自变量换作0或1/a时, f(x)的记忆表中没有对应的表项, 所以输出结果就是抽象的表达式. ' ^0 H. A8 ~1 Z6 f
在Maple中, 要真正完成一个函数的定义, 需要用算子(也称箭头操作符):
( b( |# p. _4 d: e; P5 H3 e% v. L > f:=x->a*x^2+b*x+c;
5 V" \' D" S3 | s2 l& u7 V6 k$ l
> f(x),f(0),f(1/a);
3 M+ D2 ?. Q6 F8 l5 {2 `
9 d; p5 O2 G2 {+ |- s8 n 多变量的函数也可以用同样的方法予以定义, 只不过要把所有的自变量定成一个序列, 并用一个括号“()”将它们括起来(这个括号是必须的, 因为括号运算优先于分隔符“,”).
+ _5 Y$ k. R7 H6 V! W0 w > f:=(x,y)->x^2+y^2;% p9 H& C0 c: b+ j% `
" j/ G2 I- y9 F; b
> f(1,2);
/ L/ N( j. ]! H/ M% e+ J & k: s* m. e8 ~. z0 ^
> f:=(x,y)->a*x*y*exp(x^2+y^2);, U! U \4 n# F7 A: ^ r7 u
0 }. ^- c( V- _( E' Y
综上所述, 箭头操作符定义函数的方式一般为: 7 O, L% `4 c/ n) q
一元函数: 参数->函数表达式3 u9 n& Q: g) D# ?8 K0 Z
多多函数: (参数序列)->函数表达式
' q- g) k5 m8 L0 W4 o, y" p$ Z( M- w 无参数函数也许不好理解, 但可以用来定义常函数:
: `8 V: U* m9 M > E:=()->exp(1);, f P7 a0 H8 h4 Z
2 `; K% {, U( X c
> E();8 s8 w4 y+ j4 p! A' R3 j
3 u. y. Q* L5 y9 l+ q3 f > E(x);
' {1 i: e4 U c% ~* T8 s3 _8 _; F0 v! W 2 W- D# L! a4 t- a. K4 S
另一个定义函数的命令是unapply,其作用是从一个表达式建立一个算子或函数. 2 K" q" y/ j b" k5 M2 q
定义一个表达式为expr的关于x的函数f的命令格式为: f:=unapply(expr, x);
$ H) X5 Y# {' a1 P6 M \ 定义一个表达式为expr的关于x,y,…的多元函数f的命令格式为: f:=unapply(expr, x, y, …);
; l1 n M" [+ H9 q# W( \7 H# t6 }$ o > f:=unapply(x^4+x^3+x^2+x+1,x);8 n* j8 c& B$ \3 A: f0 g
9 @8 l. g2 M3 `1 F > f(4);. y! s% w+ \8 ^& J) C
+ L0 F8 k& {$ L+ z$ W! K9 L8 @1 A
> f:=unapply(x*y/(x^2+y^2),x,y);
7 T, r1 W [' [. y5 A3 w5 {3 g J ) t) t1 I. G+ K1 M3 {, D) F" @' r
> f(1,1);
' N% X7 U/ k" ~6 L7 P; f+ e
# N( i' N: Y; H1 k' B) Z% a 借助函数piecewise可以生成简单分段函数:$ [ E* {/ J8 A# }/ n
> abs(x)=piecewise(x>0,x,x=0,0,x<0,-x);5 U. p0 Y# O |+ q4 u; j1 _6 p
% b. r: p- M h, o2 G% d 清除函数的定义用命令unassign.
2 R% k% N' i' I; S, u1 ~+ P" B > unassign(f);
0 u) o3 X! l/ K3 f ~ > f(1,1);
8 f$ O" w8 k9 D3 L% |/ j
|( K1 u! ?- ^) h# p 除此之外, 还可以通过程序设计方式定义函数(参见第6章).
! L7 L* D! \) {. A% `% a" c" L/ q 定义了一个函数后, 就可以使用op或nops指令查看有关函数中操作数的信息. nops(expr)返回操作数的个数, 函数op的主要功能是获取表达式的操作数,其命令格式为:
. p, N+ K- p O op(expr); / A% G" w- l8 r+ A% b9 W. G$ @
op(i, expr);
9 |% ^8 ~: k6 o op(i .. j, expr);
( S# f3 I2 p `1 e6 i" o nops(expr);5 Q: j0 S% U @! h* w7 u) I
如果函数op中的参数i是正整数,则op取出expr里第i个操作数, 如果i是负整数, 则其结果为op(nops(expr)+i+1, expr); 而i=0的情形较为复杂, 当expr为函数时, op(0, expr)返回函数名, 当expr为级数时, 返回级数的展开点(x-x0), 其它数据类型, op(0, expr)返回expr的类型.
9 M8 u: H# d1 \$ _3 {" R 命令op(i .. j, expr); 执行的结果是expr的第i到第j个操作数, i..j中含负整数时的情形同上.
- q0 E- F9 I- f: n& ^ 命令op(expr); 等价于op(1..nops(expr), expr);
( T8 c& d' b0 B' Y: R0 [ 特别地, 当op函数中i为列表[a1, a2, ..., an], 则op([a1, a2, ..., an], expr); 等价于op(an, op(..., op(a2, op(a1, e))...));
- j$ n0 o* X0 n8 C* k6 g, Z 而当expr为一般表达式时,nops(expr)命令返回的是表达式的项数, 当expr是级数时返回级数每一项的系数和指数的总和.
, S0 I. T( b8 ]4 w > expr:=6+cos(x)+sin(x)*cos(x)^2;
' L; a# W3 _/ }. H J! }- {
5 a, p4 N0 m3 a" U5 ~# g- A \ > op(expr);$ x2 B+ u/ A9 [
% e4 a: V5 `% x7 }+ s$ f > nops(expr);
2 x! ]1 t' j: J+ L6 T8 P ' h2 e, z/ Y( S( D! |& ?8 S0 [
> p:=x^2*y+3*x^3*z+2;
7 v) b7 @' ^* h3 I: s7 J
4 z' g( ^3 ^0 B, a; }! A > op(1,p);, D/ E! w$ Y; {1 E! Z5 @8 L
6 j0 W+ H- \9 d" p1 U$ e1 n > op(1..nops(p),p);
1 {8 k. ^' a& r# ]. l8 }
( N% ?: r+ d3 C \* T7 N > op(op(2,p));
- e7 j- E0 n; _* ^! | % v9 \% S- Q0 o. r% s. D( g3 W
> u:=[1,4,9];
# S5 J5 ?4 [0 [. L' k 8 _2 j. K3 b% P# }5 p5 K
> op(0,u);
' I5 w/ X( k: F' K
! j% ^8 c3 b# t1 p, v, C% `; H* \ > s:=series(sin(x),x=1,3);# N. B3 F/ u8 h4 o; ^0 o
0 @9 z% I) w" g7 v; ]
> op(0,s);% X$ \9 A% w% _. B
+ S, K4 c7 p U0 X. Q/ [0 J
> nops(s);& i9 \1 Z+ ]/ X' d6 D7 n
2 A e* ]$ \4 D: M2 k# K. f
下面一个有趣的例子说明了Maple在处理算术运算时的“个性”:5 V. Y$ s% v, H) l. j
> op(x*y*z);3 l5 x$ F8 S5 t
2 S$ x0 o# T1 H( o) w; f) I
> op(x*y*z+1);
$ ]% P3 ^& D% G: o5 @5 a
; P% c% H2 T" K- W1 x; c& G8 ` 2.2.3 Maple中的常量与变量名
) K- }1 X( K' f5 _$ q+ w. \* m* h 为了解决数学问题, 一些常用的数学常数是必要的. Maple系统中已经存储了一些数学常数在表达式序列constants中:
! d9 h$ o. [& P3 W8 B > constants;
]9 r+ f/ {' w1 E% P1 H. ~4 k# D9 x
8 @3 ?( E5 ~6 s0 T+ x1 \4 U 为了方便使用, 现将上述常数的具体含义列示如下:
) T9 [: z3 V& a: v: f' i/ S 常 数 名 称 近似值
$ D- r! H/ n9 C* c( z 圆周率 2 q+ h; T, ]& `7 X
Pi 3.14159265359 x4 g/ n5 U) o; r: T4 u
Catalan常数
0 A h6 }' E5 ` Catalan 0.9159655942
" ~2 O. @$ P6 w$ ?* T Euler-Mascheroni常数
$ ~% `) ^* i3 v" Q1 o3 c, g% I gamma 0.5772156649
$ P- Q! s( Y- x4 d0 Z8 W ' N/ h; F7 `$ b2 ^1 `( U
infinity 9 z; x( d7 Z4 S1 P" N+ N# z+ a
, P7 _8 C" |6 O+ m' o' | 需要注意的是, 自然对数的底数e未作为一个常数出现, 但这个常数是存在的, 可以通过exp(1)来获取.
* u8 Y3 e' I# n/ n3 q- J% R 在Maple中, 最简单的变量名是字符串, 变量名是由字母、数码或下划线组成的序列, 其中第一个字符必须是字母或是下划线. 名字的长度限制是499个字符. 在定义变量名时常用连接符“.”将两个字符串连接成一个名. 主要有三种形式: “名.自然数”、“名.字符串”、“名.表达式”.
" G% }1 W% d; m7 B8 d. L* Y% E' k 值得注意的是, 在Maple中是区分字母大小写的. 在使用变量、常量和函数时应记住这一点. 数学常量 用Pi表示, 而pi则仅为符号 无任何意义. 如g, G, new_term, New_Team, x13a, x13A都是不同的变量名.
% v7 N& B- d; m: X% p/ C/ m 在Maple中有一些保留字不可以被用作变量名: ( e% q8 E+ _4 o9 ]5 U/ j. ?, _
by do done elif else end fi for
0 g7 |# g1 W" g" S- u' W: l from if in local od option options proc + m1 C4 ]; ~) D9 R, S/ X
quit read save stop then to while D% ^6 h" I9 f% U1 G# o: t
Maple中的内部函数如sin, cos, exp, sqrt, ……等也不可以作变量名. ! h% q6 h4 G: O0 n. i8 h! A
另外一个值得注意的是在Maple中三种类型引号的不同作用:
* K+ c# }8 H3 d ` `: 界定一个包含特殊字符的符号, 是为了输入特殊字符串用的; % W3 M5 G( X4 N) f0 s
' ': 界定一个暂时不求值的表达式; 2 c5 C' V. g- ^. E' {! |& D
" ": 界定一个字符串, 它不能被赋值. & d' h3 g) ]* r5 A2 d9 i
2.2.4 函数类型转换
; E4 e9 C: y: i* M8 d/ R 函数类型转换是数学应用中一个重要问题, 譬如, 将三角函数转换成指数函数, 双曲函数转换成指数函数, 等等. 在Maple中, 实现函数类型转换的命令是convert. 命令格式:
3 [* J) g4 Q' H" b- x4 M convert(expr, form); #把数学式expr转换成form的形式3 S/ H, a7 B9 ~3 E; t; |( e( E
convert(expr, form, x); #指定变量x, 此时form只适于exp、sin、cos, K; k! P |# J3 ]4 {# u) K$ u
convert指令所提供的三角函数、指数与函数的转换共有exp等7种: 5 t% s; i4 ?# i, }9 Q
(1) exp: 将三角函数转换成指数
: q, P L8 @& j9 [5 R0 Y L; n (2) expln: 把数学式转换成指数与对数+ h8 J8 h0 D6 A2 ~5 i, v8 G
(3) expsincos: 分别把三角函数与双曲函数转换成sin、cos与指数的形式, l. \6 [: V$ u: \$ Y& ]( k6 ?. g
(4) ln: 将反三角函数转换成对数: B7 O. u, H0 Q) I/ X. N6 j
(5) sincos: 将三角函数转换成sin与cos的形式, 而把双曲函数转换成sinh与cosh的形式
" ~) S; x: D- M J0 x; G, z; ~3 C (6) tan: 将三角函数转换成tan的形式* U& G" z2 D/ n/ x6 }: {
(7) trig: 将指数函数转换成三角函数与对数函数+ h. z- z3 T1 w, d; J- A8 u
> convert(sinh(x),exp); #将sinh(x)转换成exp类型0 g" O3 | ~0 c* d
0 }4 B$ b4 O: {6 ? > convert(cos(x)*sinh(y),exp);: K B2 Z" H0 ^& P4 C
5 U# y3 W0 X+ k: K4 g
> convert(cos(x)*sinh(y),exp,y);
& w+ u( _' d) o5 [' Y+ y$ K ! H4 C7 X0 w9 _* Y
> convert(exp(x)*exp(x^(-2)),trig);( P6 d* u# {8 f% y; @! C" \
- g- l/ d( O- c9 m, _8 |! o
> convert(arcsinh(x)*cos(x),expln);' d/ ~" o. ~1 h+ p1 p/ b9 d
2 z, C/ t2 O* c' @, v, u
> convert(cot(x)+sinh(x),expsincos);3 y4 n# n- ?. P8 l, B
+ ` @8 o2 P& C6 R% `: O( a4 L
> convert(arctanh(x),ln);
2 h9 M2 C5 t& O$ e U
4 z" ^9 a* d+ c- n4 F( e, [5 u convert在有理式的转换中也起着重要的作用. 在有关多项式运算的过程中, 利用秦九韶算法可以减少多项式求值的计算量. 在Maple中, 可以用函数convert将多项式转换为这种形式, 而cost则可以获取求值所需的计算量. 注意: cost命令是一个库函数, 第一次调用时需要使用with(codegen)加载. 例举如下: ( P, l( P1 r4 Y) S' p9 o. H
> with(codegen):, j: u+ O- n( l6 M! M
> p:=4*x^4+3*x^3+2*x^2-x; Q8 B3 L* C; b
0 q( E/ S3 j+ r; s& W v4 L > cost(p);
. h* a6 `: i+ v* Q1 U) f
3 e: {1 _5 X5 Z" g > convert(p,'horner'); #将展开的表达式转换成嵌套形式
5 |: ^# n: Y9 q$ X9 b
( Y/ `# L6 r- k* ^8 I w > cost(%);
: b, ^6 [# l% |' ?' C. k
, B+ m& ?# Z- Q4 T* T( Z# J 同样, 把分式化成连分式(continued fraction)形式也可以降低求值所需的计算量.
; B P! R7 C7 h > (1+x+x^2+x^3)/p;+ t! h; j, Y. z; e' [
* h- e. T* [5 [5 ?
> cost(%);
% [5 K2 `& S- J* c* v# B, ?9 X
8 Y' d, A' X s3 H# O% C B" t, _5 T& ` > convert(%%,'confrac',x);
1 u+ O Y% X1 n
, Z& w( W& \) n+ B > cost(%);
: b) \- D n/ b. l! a % L4 x: h% s0 Z# i
在某些场合下(比如求微分、积分时), 把分式化成部分分式(partial fraction)也就是几个最简分式的和式的形式也可以简化运算, 但简化程度不及连分数形式.
1 j$ o) U$ J& \# R, k > convert(%%, 'parfrac',x);, o. Q3 _4 J7 _1 C2 Y R1 `$ A
; e, p* W/ ]5 J5 w+ H9 {
> cost(%);) F# I1 G v& j
6 d0 }; I5 e& I5 H$ ?* s: H 而把分数转换成连分数的方法为:" j" ]9 L6 ` q, K* E* M5 {9 T( @
> with(numtheory):$ G6 z7 e7 p1 D* ]3 F
> cfrac(339/284);7 x; e v" f* m# y5 D' W
8 ?* I8 K# w# B% k
2.2.5 函数的映射—map指令
8 W& ]% B8 F2 T1 T. j9 L 在符号运算的世界里, 映射指令map可以说是相当重要的一个指令, 它可以把函数或指令映射到这些结构里的元素, 而不破坏整个结构的完整性. 命令格式为:: u8 m) }; ?6 V$ g0 V( ^- X
map(f, expr); #将函数f映射到expr的每个操作数
! h) @0 B2 j6 o3 v' ^- t- [ map(f, expr, a); #将函数f映射到expr的每个操作数, 并取出a为f的第2个自变量$ ]1 n% Z/ a6 B
map(f, expr, a1, a2,…, an); #将函数f映射到expr的每个操作数, 并取a1~an为f的第2~n+1个自变量) T( I) K Z9 q1 J7 k
map2(f, a1, expr, a2, …, an); #以a1为第1个自变量, expr的操作数为第2个自变量, a2为
# w0 e! L' L& C2 W8 {+ i7 v/ W 第3个自变量…, an为第n+1个自变量来映射函数f
4 Y2 _$ P+ g) }; v+ ~& U > map(f,x1+x2+x3+x4,a1,a2,a3,a4);
/ T5 C0 |" ^) o/ o 7 C- z& b. Y) d
> f:=x->sqrt(x)+x^2;
{% T# \* r! ]% E' P6 L 0 Q2 b/ v$ }" `% x
> map(f,[a,b,c]);! x6 ~+ a4 x4 T- N2 \! G! G7 Y; z' ]
' w2 J1 z6 B' |: c7 i > map(h, [a,b,c],x,y); ' d: \6 Y8 U2 I$ u% n& G3 X, |' L
- q1 z$ h& Q' s
> map(convert,[arcsinh(x/2),arccosh(x/2)],ln);1 r; @3 w1 w% F' L; u
! w7 w3 c" g9 @% c
> map(x->convert(x,exp),[sin(x),cos(x)]);* n9 L* \. _ M( ^" h L0 C
" T0 e% R5 a% H* C- }$ O 上式的映射关系可通过下式理解:& u) S" Z0 p7 V4 p2 {
> [convert(sin(x),exp),convert(cos(x),exp)];! P. h9 X. ^( l$ N# _$ V! q
) E5 q; m, z, z2 C4 M- \ > restart: ) T( N# t* ~+ A
map2(f,a1,x1+x2+x3+x4,a2,a3,a4);
/ X- T$ Q9 K7 x/ y4 y% Q 6 _* r5 M6 q( _; s' O- ]8 i9 v$ `
> map2(max,k,[a,b,c,d]);
. w4 k( }# {' `+ ]9 D
8 c v1 ?! [" H$ ^+ g 再看下面示例: # ?4 c/ Y/ I3 L: v, b
> L:=[seq(i,i=1..10)];
: a* g7 O; q d( ?; q
" p1 f8 O0 u4 f& @2 ] > nops(L);
- Q, K% i8 b9 Q* G9 X
' G7 g/ ]- p; v2 y2 `5 C8 L# q > sqr:=(x)->x^2;
/ N2 q. z; E' ~2 u' C) C Y. J' o3 t3 V7 }6 S
> map(sqr,L);& ~4 g) b/ a2 k ]
& s1 a8 m& H+ z: ?6 u1 {
> map((x)->x+1,L);8 c% m5 w1 i& J6 y6 D2 r
0 b2 l; G/ R/ f) q* T% l3 G: z > map(f,L);
+ o: K7 ?2 E' o; f5 k {0 D - ~ C. N' p) D5 K1 o e2 E
> map(f,{a,b,c});, X5 @( ?$ p& F c* z
5 o3 p: u' S, d" d
> map(sqr,x+y*z);
9 b) \1 I9 e% ?" Y, N3 B
: F# d0 D {! }' H r > M:=linalg[matrix](3,3,(i,j)->i+j);9 ^8 {& i: F! Y% J i) e" J8 F2 J
2 S, m: o4 y4 g. m8 f% N; k > map((x)->1/x,M);$ [4 |" F7 R+ F' J0 N. J
0 k! U! w, V1 w' g5 N
3 求 值1 Y7 s7 V3 g) u* `& e5 }( K+ ]
3.1 赋值
. n, X g4 O) a 在Maple中, 不需要申明变量的类型, 甚至在使用变量前不需要将它赋值, 这是Maple与其它高级程序设计语言不同的一点, 也正是Maple符号演算的魅力所在, 这个特性是由Maple与众不同的赋值方法决定的. 为了理解其赋值机制, 先看下面的例子.
8 @( Z5 |# e# L4 f: J > p:=9*x^3-37*x^2+47*x-19;
2 M2 }, b' X3 V8 }2 N, n3 x. { 8 c# s; Z: U, Q! }6 W8 s7 w( y! ^
> roots(p);3 E0 [8 n% C& }# r. P6 d
% Z" a% n& i* r, @% m: z > subs(x=19/9,p);; M- ?( y4 C# n' c+ L% v8 z* D7 Z9 X
+ ~2 q! L j, D5 E& |' ?2 t6 b5 E$ P
在这个例子中, 第一条语句是一个赋值语句, 它的作用是把变量p和多项式9x3-37x2+47x-19相关联, 在此之后, 每当Maple遇到变量p时就取与之唯一关联的“值”, 比如随后的语句roots(p)就被理解为roots(9x3-37x2+47x-19)了, 而变量x还没被赋值, 只有符号“x”, 通过subs语句得到将p所关联的多项式中的所有x都替换成19/9后的结果, 这正是我们在数学中常用的方法—变量替换, 但此时无论x还是p的值仍未改变, 通过“> x; p;”这样的简单语句即可验证.
9 B9 n* c; B* I( |5 N 3.2 变量代换1 ]7 o5 H2 }# W; x* z
在表达式化简中, 变量代换是一个得力工具. 我们可以利用函数subs根据自己的意愿进行变量代换, 最简单的调用这个函数的形式是这样的: & U) O! y/ ?# W, C$ w& ~0 U
subs ( var = repacedment, expression);
( q6 s" ]7 ^6 h. A/ N% X4 E6 [5 I 调用的结果是将表达式expression中所有变量var出现的地方替换成 replacement.
9 l/ C% N. o+ e0 u& C > f:=x^2+exp(x^3)-8;9 F+ M3 F1 L! O0 g& g6 u
9 L1 c, q5 m/ S4 p
> subs(x=1,f);
9 m$ a6 O% N8 N, r5 f$ Y * o: j S4 g. T O) R: f6 `, w
> subs(x=0,cos(x)*(sin(x)+x^2+5));
" m$ Y6 Z# c4 A7 B* H) r
A6 x, M) Q% ~3 L( s9 s 由此可见, 变量替换只得到替换后的结果, 而不改变表达式的内容, 而且Maple只对替换的结果进行化简而不求值计算, 如果需要计算, 必须调用求值函数evalf. 如: 2 [4 h0 k' q7 @. A' W' j
> evalf(%);
' r( _, w. ~* z; J; s$ Z & w6 v" }# p( ]; i8 q& }0 p5 C
变量替换函数subs也可以进行多重的变量替换, 以两重代换为例: # B. A$ V% X- [! q5 s9 U$ u J
subs (var1 = repacedment1, var2 = repacedment2, expression), [% K/ W0 I) Z2 y: P
调用的结果和按从左到右的顺序连续两次调用是一样的, 也就是先将expression中的var1替换成replacement1, 再将其结果中的var2替换成replacement2, 把这种替换称作顺序替换; 与此相对, 还可以进行同步替换, 即同时将expression中的var1替换成replacement1, 而var2替换成replacement2. 同步替换的调用形式为:
6 ]. g4 _. {, {7 }. c8 y# d2 R subs ( {var1 = repacedment1, var2 = repacedment2 }, expression)
& Z3 L, m! y( j3 Q L5 g% U7 y* [# \ 下面通过例子说明这几种形式的替换.
. Y/ e4 O" I( e > subs(x=y,y=z,x^2*y); (顺序替换)
* H/ }/ |5 `' `8 h
% l; T4 x5 c: `2 k+ v% W > subs({x=y,y=z},x^2*y); (同步替换): ]0 g2 W; i: A: p% T7 c4 a
) D# r; L# D4 c% p' k
> subs((a=b,b=c,c=a),a+2*b+3*c); (顺序替换)) Q& b1 j0 D& W) ?
1 k, A' z! {/ n( K; \& G > subs({a=b,b=c,c=a},a+2*b+3*c); (轮 换)) ^% c$ W' t1 L7 W0 [* _- Z
, O1 b% Q3 L. ~. I
> subs({p=q,q=p},f(p,q)); (互 换)
) d0 |' b, }0 c, T . U; l3 @8 L- d! A/ |5 U8 U
3.3 假设机制
6 D% c: d5 z$ e$ k# r- n- K- } Maple是一种计算机代数语言, 显然, 很多人会尝试用Maple(或其他计算机代数语言)解决分析问题. 但由于分析问题与处理问题的考虑方法不同, 使得问题的解决存在某些困难. 例如考虑方程 的解. 如果k是实数, 结果显然是x=1, 但如果k是 的复根, 为了保证解x=1的正确性, 必需添加附带条件: 也就是当 时x=1. 这是一个对结果进行正确分析的例子. 然而从代数的角度考虑这个问题时就会把k当作不定元, 此时k没有值, 从方程两端去除k的多项式是合法的, 只要这个多项式不是零多项式即可(这一点是可以保证的, 因为其所有系数不全为0). 在此情况下x=1就不需要任何附加条件. 计算机代数系统经常采用这种分析的观点. " Z$ T2 m$ p j4 s7 N
在Maple中, 采用分析观点解决这类带有一定附加条件的实用工具是函数assume, 其命令格式为: assume(x, prop);
0 a$ F! I; P* N2 O5 X; S6 A( I0 D1 Q 函数assume界定了变量与变量之间的关系式属性. assume最普遍的用法是assume(a>0), 该语句假设符号a为一个正实常数; 若假定某一符号c为常数,使用命令assume(c,constant); 另一方面, assume可以带多对参数或多个关系式. 当给定多个参数时, 所有假定均同时生效. 例如, 要定义a<b<c, 可以用assume(a<b, b<c); 同样地, 要定义0<x<1, 可以用assume(0<x,x<1). 当assume对x作出假定时, 以前所有对x的假定都将被删除. 这就允许在Maple中先写“assume(x>0);”后再写“assume(x<0);”也不会产生矛盾. " a) _1 \8 E) B
> Int(exp(-s*t),t=0..infinity);# P h# a$ ]6 X) D7 {, ~
, f) ]" [7 M& J- @6 D > value(%);9 v) |/ f- k* z, n( ?$ y J0 a$ u
Definite integration: Can't determine if the integral is convergent.: L- s& F0 J/ }% C C
Need to know the sign of --> s- X i& i2 Q1 o T: k- l) Z* y
Will now try indefinite integration and then take limits.+ a/ G! f0 c6 l' N8 N- f
+ \* ]5 a; G8 x' ^! _# {1 c
> assume(s>0);( J0 j1 Q' J6 \1 K% h1 i
> Int(exp(-s*t),t=0..infinity);' Q8 e: j8 j- s l1 s! W
0 o3 ?! A8 [9 X- u0 k > value(%);0 {$ }! K! }2 p% h
. p; y6 i( b" Y: x4 R% ]7 i3 v( [ 3.4 求值规则
- a& ]* F0 _. |5 d6 {/ D6 r! [+ W 在多数情况下, Maple的求值规则设计为做用户期望的事情, 但要做到这一点很困难,因为不同的人在相同的情形下会有不同的期望. 在大多数情况下, 全局变量被完全求值, 局部变量被一层求值. 而由符号' '界定一个暂时不求值的表达式, 单步求值仅去掉引号, 不作计算, 这也是允许取消指定名字或清除变量的原因. 如下例: 3 \4 v3 s! e7 K+ s/ [) @7 I# C
> x:=y;
2 f) C4 K$ v6 T& F% r
2 I$ N" a Y+ J, h% ~* ^) p* o5 z > y:=z;
_. o; ~7 _* M5 W( n
3 b" h2 ?0 T' P$ j7 } > z:=3;
9 s q0 U. c2 t4 d$ @; J9 ] 6 i. |- }+ R$ w8 t/ K4 e
> x;
' t$ H' J5 i6 N7 B# t' P, L
6 Z" {3 L8 K6 b4 T% ^* z& Z > y;
a2 Z9 y# I; `# Y
1 D9 ]( A2 V O# k! r: _9 z > x:='x';# U: ]1 r$ R9 w; B8 U! U1 Y" s
1 @. o, Y$ x( h$ R. F5 F
> x;
, P7 H0 p5 v2 l% }2 X/ l . }# Y+ w' J! F3 N6 a! ?, V, W$ d* `
> y;
6 u$ W, m4 c o& I3 E, L( \7 t7 U2 J
" `) i/ p2 I) }& b* u 对于不同的问题, Maple设计了不同的求值命令. 现分述如下: + }- D: Y( ]. T+ F* Z7 Q& _; J+ A% p
1) 对表达式求值& e/ v0 |) u2 {/ |; L; K, U O0 ?
命令格式: eval(e, x=a); #求表达式e在x=a处的值
# B9 J+ O! S! d3 g: A4 e& o3 r eval(e, eqns); #对方程或方程组eqns求值
5 K4 [5 K1 A- y7 C1 v# W eval(e); #表达式e求值到上面两层1 `5 S% s5 h6 f( w. |
eval(x,n); #给出求值名称的第n层求值
$ K4 P- Y2 W0 Q" t8 s' Y: ^ > p:=x^5+x^4+x^3+x^2+x+73;
1 V5 U; b4 Q: m' K8 ^ 4 P& \8 Y7 K! ?3 @$ e
> eval(p,x=7);! d1 {4 o4 @* u5 O1 l
3 b$ ^4 ~* ?% i1 z% S+ f > P:=exp(y)+x*y+exp(x);
7 Y! ^1 k4 U: j( E# u
. K$ M6 v$ [8 h c > eval(P,[x=2,y=3]);
% r* E0 {# |# x) B& ^" L: P
8 u+ f1 i: \8 d2 X! ?, C 当表达式在异常点处求值时, eval会给一个错误消息. 如下: " G7 Q8 C' H; j( t
> eval(sin(x)/x,x=0);% { ?* `. X. G2 g" k
Error, numeric exception: division by zero7 k+ i9 P+ o6 w, J$ Y
下面再看使用eval进行全层求值或者对名称几层求值的示例:
7 B+ F! ^& ?/ w+ r o > a:=b: b:=c: c:=x+1:) A5 T5 {2 H" A1 p5 m8 g1 T z
> a; #默认的全层递归求值
+ Q8 O0 n$ Y- ^
$ V% N; V6 T- b, J7 b9 r, \ > eval(a); #强制全层递归求值 ^5 e2 D- ^# M& S
9 H8 u) p8 G* s9 t
> eval(a,1); #对a一层求值1 t* |! s ]( B7 ]. \1 w$ w. ~7 c
1 x& ~; U; C3 S5 s& I+ r8 U4 B > eval(a,2); #对a二层求值0 S9 k. E3 [) g* V
7 A" ]. z0 ~/ @7 G' s
> eval(a,3); #对a三层求值- s9 x. `4 q& q, j
& D+ h* c$ E) B4 }/ c > eval(a,4); #对a四层求值7 n0 R$ ~) a' V8 p
# k' b6 k6 M8 T' S! d8 a9 Y8 m 2) 在代数数(或者函数)域求值; U+ J& Q5 C- z3 N3 E
命令格式: evala(expr); # 对表达式或者未求值函数求值
; `5 ?: s( A3 q/ l: b& g, z evala(expr,opts); #求值时可加选项(opts)
# F* |; H0 j" i/ T' y 所谓代数数(Algebraic number)就是整系数单变量多项式的根, 其范围比有理数大, 真包含于实数域, 也就是说任意实数都是整系数多项式的根(如 就不是任何整系数多项式的根). 另一方面, 代数数也不是都可以表示成为根式的, 如多项式 的根就不能表示成为根式的形式. $ g y4 P, C, P' G
代数数的计算, 算法复杂, 而且相当费时. 在Maple中, 代数数用函数RootOf()来表示. 如 作为一个代数数, 可以表示为: 3 h% X9 G- e7 \7 n. ]% e
> alpha:=RootOf(x^2-3,x);
! a$ h* t) D+ i7 I6 f2 s# X
, M! _$ n* g5 l) I; i, Y > simplify(alpha^2);
: d; f8 T. S( \, m, i$ t 0 {" R: A+ ]5 F" a1 V$ T5 T3 @
在Maple内部, 代数数 不再表示为根式, 而在化简时, 仅仅利用到 这样的事实. 这里, Maple用到一个内部变量_Z. 再看下面一个例子,其中alias是缩写的定义函数,而参数lenstra指lenstra椭圆曲线方法:
3 }+ P0 Q, S. ?7 S9 B! u q- t2 d > alias(alpha=RootOf(x^2-2)):4 {7 L6 v9 |; T* H0 ]9 m' V5 y
> evala(factor(x^2-2,alpha),lenstra);9 ^" c/ V* U5 ~" s, h
' I; Q* q9 D! l* S* ]' B
> evala(quo(x^2-x+3,x-alpha,x,'r'));
7 d$ A9 D2 t$ G% c& ~: e + u( p, O1 P$ M+ k
> r;0 c W. x4 ~# K2 R
, D/ u* N+ J H; C
> simplify(%);
# I# o$ k x" p1 o
& U- J5 V0 k. v+ W# e* C: S2 R 3) 在复数域上符号求值
: }" \% ?) n9 k 操纵复数型表达式并将其分离给出expr的实部和虚部的函数为evalc, 命令格式为:* N9 O: V' e6 E E
evalc(expr);
3 H) a( f8 j- J( n, ~ evalc假定所有变量表示数值, 且实数变量的函数是实数类型. 其输出规范形式为: expr1+I*expr2. / D& K' t( a: c, i
> evalc(sin(6+8*I));2 P5 m- ^( z: N0 A- X2 x2 w) g' K
! ]% G, o% Q- ]4 f7 P
> evalc(f(exp(alpha+x*I)));
7 G6 r0 K2 ^# i
* Y1 Y: v- n3 P0 `! R( t- m > evalc(abs(x+y*I)=cos(u(x)+I*v(y)));
! }' }' @; ^: W1 I
2 ]7 V) K0 u% J 4) 使用浮点算法求值
+ K( t- `9 ?. D) t; M 浮点算法是数值计算的一种基本方法,在任何情况下均可以对表达式expr使用evalf命令计算精度为n的浮点数(n=Digits), 如果n缺省, 则取系统默认值, 命令格式为: evalf(expr, n); ?% P' U/ z% X+ \: p% S
> evalf(Pi,50); - X( }$ b, x) p6 @, u- o- z
9 q# @5 d. a, E* d2 T1 | > evalf(sin(3+4*I)); 8 H- d, m$ `6 J" \5 @ ^
# V+ U" c5 J5 ~& }$ C > evalf(int(sin(x)/x,x=0..1),20);
+ C" e6 L) A' c( c" c " h5 D! ?5 P( M9 a, C0 k K
5) 对惰性函数求值# v4 h+ b8 l6 Q
把只用表达式表示而暂不求值的函数称为惰性函数, 除了第一个字母大写外, Maple中的惰性函数和活性函数的名字是相同的. 惰性函数调用的典型用法是预防对问题的符号求值, 这样可以节省对输入进行符号处理的时间, 而value函数强制对其求值. 对任意代数表达式f求值的命令格式为: value(f);
" f- _7 q2 I6 M2 } > F:=Int(exp(x),x);* f6 B( \' A4 U9 }) Z% O
! a1 U6 D% I2 N* A$ s( Y3 _- {
> value(%);
# J- H, x" B" G6 J* U
2 C0 F, Z$ T( z# e! A > f:=Limit(sin(x)/x,x=0);$ l* v3 }# B# E7 J) s0 q
3 k2 i* s7 s' S4 g. S! k1 p
> value(%);( x+ E$ z, n- r1 Q
+ W4 D3 W6 ?. ~- |7 ~9 R+ O! h Z
另外, 将惰性函数的大写字母改为小写字母亦即可求值. 如下例:
9 G' l7 c- Q, n T' ^/ f& b: d- X& C > Limit(sin(x)/x,x=0)=limit(sin(x)/x,x=0);8 }" d M* F/ b' S, B) y/ \
5 U( P3 c1 T1 Q8 H2 c1 Z' h
4 数据结构/ a& S+ P# f$ v b; ]$ f) N' B1 }
Maple中有许多内建的与FORTRAN、C或Pascal不同的数据结构. 主要的数据结构有序列(sequence)、列表(list)、集合(set)、代数数( algebraic number)、未求值或惰性函数调用、表(table)、级数(series)、串(string)、索引名(index)、关系(relation)、过程体(process)以及整数(integer)、分数(fraction)、浮点数(float)、复数(complex number)等数据结构, 而矩阵(matrix)在Maple中表示为阵列, 是一种特殊的表.
8 q& {2 H1 L7 Y' W* j 4.1 数据类型查询3 x1 m" e k! F4 q+ r c ^/ ?! ^
在Maple中, 用whattype指令来查询某个变量的数据类型或特定类型, 命令格式为: " e, k. s1 k- N, C- c
whattype(expr) # 查询expr的数据类型
2 N6 E. @5 N& s type(expr, t) # 查询expr是否为t类型, 若是则返回true, 否则返回false5 q) @5 x- n; I% _0 t
> whattype(12);
) V& D; }7 c7 ?& k g3 b( n! Y" B% R! k
> whattype(Pi);
$ u$ Y; g* ]( ]$ L' v, Y
" C# ]2 Q5 \/ x$ X > type(1.1,fraction);
* A! @6 x b3 H L6 ?0 U
+ y& }* Y, z& @$ m/ X8 r > whattype(1.1);
9 L6 t0 Y2 T8 |* c
! G/ o- u8 S% I$ C `2 c 4.2 序列, 列表和集合8 a1 J& L5 }; C7 n& }% h
4.2.1 序列
. ^/ w! L5 s& T; Q 所谓序列(Sequence), 就是一组用逗号隔开的表达式列. 如:
& }8 k E6 H [3 T, T: L0 r > s:=1,4,9,16,25;
" u+ [6 b# h6 h9 f9 R
( W" E9 q, X! N) v6 j > t:=sin,com,tan,cot;% P( Y) E7 H% }7 ~
' L1 X0 l* t1 V/ ] 一个序列也可以由若干个序列复合而成, 如: ) z7 q# K* ]1 G/ C
> s:=1,(4,9,16),25;
! e# x' e& }2 C
$ a) k) U* L2 N: }. F# C > s,s;. m7 }8 c! l6 l$ ~
0 f& e( r) e g' K; t 而符号NULL表示一个空序列. 序列有很多用途, 如构成列表、集合等. 事实上, 有些函数命令也是由序列构成. 例如: # x- }1 v3 y# X5 \' j3 a D$ o' }
> max(s);6 L' h9 Q- s4 F% t: c) C! f
6 o! ~- N, b2 N; f > min(s,0,s);
' g( H' i0 E$ b2 v - d) C. R# p1 Q! m
值得注意的是, op和nops函数命令不适用于序列, 如op(s)或nops(s)都是错误的, 如果要使用op(s)或nops(s)前应先把序列s置于列表中. 8 f9 s6 U, H4 |- }8 a& h: ^$ y& b
> s:=1, 2, abc, x^2+1, `hi world`, Pi, x -> x^2, 1/2, 1;
2 l1 y [! v2 A7 |4 [ ) k' D# T. q; o2 G- @
> op(s);. y8 z* V( L- }$ H) h
Error, wrong number (or type) of parameters in function op
0 r) O& v# B# K: }, r+ U7 [ > nops(s);
! h6 p* o, k! ?8 d: M) z" Y8 Q6 x u Error, wrong number (or type) of parameters in function nops
! K8 s- a a& l- T l > op([s]);/ {% U, M0 A% C
1 a% u% X/ h) s) w > nops([stuff]);9 s- D) z6 }; S* Y" y# d2 C: r& C
) z7 r) M3 g8 L# G% ^4 ^/ \2 T/ Q
函数seq是最有用的生成序列的命令, 通常用于写出具有一定规律的序列的通项, 命令格式为: . X- W* W* |6 O& c! K
seq(f(i), i=m..n); # 生成序列f(m), f(m+1), …, f(n) (m,n为任意有理数)
* u" {7 C2 b6 T4 U seq(f(i), i=expr); # 生成一个f映射expr操作数的序列3 }0 `- c2 b1 x- Q' d0 L
seq(f(op(i,expr)), i=1..nops(expr)); # 生成nops(expr)个元素组成的序列4 W+ \' g1 J" }, A4 R: u X3 l. r
> seq(i^2,i=1..10);
7 h3 n' U0 Z; D8 |* R 7 X# M2 G0 g% ?- C8 O7 ]
> seq(ithprime(i),i=1..20);0 ? R N% N' {2 F5 u- ~& K. i( b
; c* y5 G2 O) S. _, J6 y
> seq(i^3,i=x+y+z);
- ]% Y! _# J- V8 X S g + T3 n9 n, q' p- C& {9 [+ v
> seq(D(f),f=[sin,cos,tan,cot]);
9 ^ t: \5 O$ Z: S9 b' o ! y1 c( B% X7 k1 h6 H0 W
> seq(f(op(i,x1+x2+x3+x4)),i=1..nops(x1+x2+x3+x4));
# t) D, d$ i$ s' c7 v3 A, F9 U
& @9 K, a4 f$ G5 E$ i( w$ ^ 获得一个序列中的特定元素选用操作符[ ], 如:
, b& C, Y; K0 d$ T > seq(ithprime(i),i=1..20);
( l8 n* Q, V( W8 { 4 C3 [1 v+ I" {$ Z
> %[6],%[17];; ~+ x( @- Q1 z6 `2 } n5 n
4 B/ n3 V, o9 K v3 G, k 4.2.2 列表
3 J$ z% S& }6 C! \& ~2 y3 R1 O7 q! a 列表(list), 就是把对象(元素)放在一起的一种数据结构, 一般地, 用方括号[ ]表示列表. 如下例: " f& O; q% C$ C+ t3 p
> l:=[x,1,1-z,x];8 V. b" {9 t/ j A i5 O
" c) p) U$ M! D H$ `
> whattype(%); ?( t* a- Q& x/ t$ F
3 n( S- u' r; z( A, i* F4 A 空列表定义为[ ].
1 }, L+ _) h: Y# T: x$ a2 T 但下述两个列表是不一样的, 因为对于列表而言, 次序是重要的:
/ ]; j \, g7 g > L:=[1,2,3,4];
* m6 J) F2 I8 ~* c1 S! t( V% D
) z+ A: W$ v! N > M:=[2,3,4,1];
( e- n' ]9 z9 [: V2 J, e/ M# [4 h1 f
# u$ F$ H/ H7 o8 Q/ [6 z5 G 4.2.3 集合. N5 s& c5 ~) w6 B" C1 Q
集合(set)也是把对象(元素)放在一起的数据结构, 与列表不同的是集合中不可以有相同的元素(如果有, Maple也会自动将其当作同一个元素), 另外, 集合中的元素不管次序. 一般地, 用花括号表示集合. ]: n0 W, N4 T9 M
> s:={x,1,1-z,x};2 v! d, k3 \+ v# J- v1 m: i' D
* H- O4 B) W9 k4 }1 F( f > whattype(%);! W, v% y; f) z1 q% |- o% @
/ W: o) x, _2 C2 a/ J, X3 L
空集定义为{ }. " ]) t' G5 w3 f* v$ J! L
函数nop返回列表或集合的元素数, 而op则可返回其第I个元素. & G( V. @6 {. W
> op(1,s);% o# Z, R4 {* d6 X
. v. \; [: R' v6 i. e; Z! Z
> s[1];
7 W4 c! g) r7 d8 ?: ?5 p! u
) {: p' x6 |( i4 o6 ~1 x > op(1..3,s);( I) G! e9 y& M1 s
7 M. Q; U# u y! l5 w! p# n > s[1..3];
/ T5 z3 j8 x5 g/ Y : }5 ]: Q) j; v, O* I
函数member可以判定元素是否属于一个列表或集合, 如果属于, 返回true, 否则返回false.
: f, M" c9 e. ^0 r& E7 d > member(1+x,s);0 E/ ~7 s; O+ A. Y
0 V( N5 N1 ?1 O6 ?# G1 u
可以通过下述方法在列表中增减元素:
% v$ T( s; d y" L, s > t:=[op(s),x]; e0 E! z; @& I, y5 u, I
: R' s2 c0 r# y' i. V! J > u:=[s[1..5],s[7..nops(s)]];
! B& b* ]# N+ N; @ 8 T! H: |5 O, W
Maple中集合的基本运算有交(intersect)、并(union)、差(minus):
4 J- e& O& m7 ]5 H8 v p3 W" } > A:={seq(i^3,i=1..10)};B:={seq(i^2,i=1..10)};
) g3 {9 E s# ^1 o
1 i* S) Q1 q% m: I/ c, S) Y5 F( w " q6 z @8 P/ j4 r
> A intersect B;
* p/ q# t! r/ `" z
+ |7 [% Q: R( p. u ~( r > A union B; 7 b0 A' L8 p0 j& g: c
; b! d: T7 Y5 G+ r0 u > A minus B;
; y: U9 }8 q+ c$ l" K4 E + k) p8 W6 Y/ J1 w# J) o2 T- x
4.3 数组和表
7 x5 v' y5 ^/ Z( U8 P) I 在Maple中, 数组(array)由命令array产生, 其下标变量(index)可以自由指定. 下标由1开始的一维数组称为向量(vector), 二维以上的数组称为矩阵(matrix). 数组的元素按顺序排列, 任意存取一数组的元素要比列表或序列快的多. 区分一个数据结构是数组还是列表要用“type”命令.
1 U+ o- z# C: L/ Z3 } 表(table)在建立时使用圆括号, 变量能对一个表赋值, 但一个在存取在算子中的未赋值变量会被自动地假定是表, 表的索引可以成为任意Maple表达式. 表中元素的次序不是固定的.
\0 Y& K' x, Y/ { > A:=array(1..4);' _8 |: `% c3 e
; h1 Q: I$ ]8 O' K/ b1 f > for i from 1 to 4 do A[i]:=i: od:' G! ?0 [2 w: A5 D/ V3 t0 c1 e& Q; N
> eval(A);
/ r6 t- ^ N& d$ P' C6 x
% g: `% `: q1 I1 e- G0 O6 O > type(A,array);8 t& i8 l1 V$ F* |
+ N0 n, T! B$ n# d" n, @, f5 h3 j/ o > type(A,list);1 E' N' Z, t" f
& w1 E% _* J0 \) u* A( R
> T:=table();- v4 W" l, a& f2 ~1 X
) c) \( _- ]% Z5 u' N2 g > T[1]:= 1;1 |( M e& q2 i' f u2 X1 F
4 J8 C$ g; S" D1 b4 W > T[5]:= 5;, ?& T; k# e! p* f9 |5 x: q2 Z+ P! h
& E- @$ a+ P0 J; J- k > T[3]:= 3;
, h" ?/ |, T0 h- \
- a" L5 [& G! g) `1 ] > T[sam]:=sally;
: K' Y' }( z& W' p7 ?
! h! n2 X/ Q2 j1 k > T[Pi]:=exp(1);
4 s; l5 |# H: t6 N7 J, |, | 3 h+ V+ j8 i) F. t) n4 i
> x:='x';
3 Y& {& o( N, q. A3 n & H" k7 c3 u6 R% P' w) w& E
> T[(1+x+x^3)*sin(x)] := 0;
1 P1 U+ J+ U! W i {& D ^ / v, y( O3 G- @- W! g) H! O* k! T
> eval(T);0 ~6 }0 Z i7 `" ^* f w1 \! F
2 o5 [- f2 |; P7 ]- b/ X9 u# F# w > T[3]:='T[3]';
: S( Z, c7 d5 a" H1 V; E 7 V& A/ R6 |6 R: ~9 d
> eval(T);
7 E6 k$ _0 u; U1 L& u8 z
* ?0 I& c: y+ w; G' d3 M 4.4 其他数据结构- S- B) `- ~7 P! T' e2 Z% M; D" G3 J
串在Maple中是很重要的, 他们主要用于取名字和显示信息. 一个Maple的串可以作为变量名, 它们中的大多数是简单的、不需要加引号的串, 但是如果变量名中包含/. 例如“diff/T”则必须把变量名用引号括起来. + }# Z% F( ?3 j$ G9 _' _3 q3 p/ r
索引名是像Database[1,2,drawer]或A[3]这样的对象, 在使用索引前不需要直接建立表, 如果不得不做, Maple会自动建立表. 索引名通常被用于矩阵和向量. 为了保证Maple建立表的正确次序, 建议在赋值前直接建立. " W# t( x' G- o. ^0 L, @7 @7 L. f
> x:=T[3];
1 y$ Z% j* s8 R2 v8 e 9 w' L. s0 b, [/ c: X% {
> eval(T);
5 X e. i* K! A. {5 Z
# j# U+ u' R. c3 |% M; ^ > T[5]:=y;1 z1 s" W) `; x) u* q
4 A; L- m! E2 G6 W9 A6 {7 J" b > eval(T);
% i3 a9 T5 y& j; a" e4 M1 I8 K9 a6 n 0 z5 g7 K% a* I4 Q, U' Y
由此可见, Maple并不直接建立T的表, 直到给T[5]赋了值. M6 i$ l* e5 E' Q/ g* n! [
数值数据结构(整数、分数、有理数、浮点数、硬件浮点数和复数等)在它们的使用中是大量透明的. 浮点数是有传染性的, 这意味着如果数值结构中有一个是浮点数, 则整个结构自动转换为浮点数. , L I* `6 s3 ^2 P9 J5 X& x
4.5 数据类型转换和合并4 d7 I/ j1 ?$ \# w! a# W, j
convert是一个功能强大的类型转换函数, 它可以实现列表和数组的类型转换:
1 v0 K+ G! R \) f' s# q > L:=[1,2,3,4];9 ?7 p, E( x8 r! `+ z
4 q6 h7 z/ Z9 x8 ^7 O5 v
> type(L,list);
* G6 P( Q' x- s; I7 r% \. O - `# k% q2 V2 n; F$ p/ ^
> A:=convert(L,array);
# \6 T& z& [) J6 L: a
- T# R; \, h9 y > type(A,list);
5 ~7 k0 X% Q- q& ^( f, h6 ^' y
# J" m, V$ F- w) Y > type(A,array);9 ?& v$ ?* p, P' ]7 ?& K& f
: `3 k; v r' N( W2 |* {) k 另一个有用的函数zip则可把两个列表或向量合并: , W, S% [0 s6 }% p
>L:=[seq(i,i=1..10)];
1 W1 w. Q: S& U- K4 K . U* ~( ^* o9 W8 h) U
> Sqr:=(x)->x^2;# W; C& e( |: n# P: C" }+ e/ Q
8 W: C) n, [. u+ q; f% `
> M:=map(sqr,L);$ V. C3 w' z5 v4 c8 {% f( j$ W
% H; F6 r+ c3 Z0 ^: U# @( F1 f > LM:=zip((x,y)->[x,y],L,M);) A8 f0 o) |" r( M
* |5 I/ R5 U; z3 Z7 t
> map(op,LM);
9 V0 t7 {) N! x* w T+ Y D, Y! K6 b
. {) ?; f# H+ Q) n4 V/ P0 | 5 Maple高级输入与输出操作* v+ u. ^8 k S8 x" U: ^' b
Maple提供了良好的接口来编辑与计算数学式. 许多时候, 我们可能需要把Maple的运算结果输出到一个文件中, 或者在一个文本编辑器里先编好一个较大的Maple程序, 再将它加载到Maple的环境里.
, t" w2 _& G2 ^$ g* { 5.1 写入文件
. x7 {/ [0 H4 H 5.1.1 将数值数据写入到一个文件/ Q/ s! w5 H! _ \ m! L$ t. q
如果Maple的计算结果是一长串的数值串行或数组, 而想把它写到一个文件时, 用writedata命令.
2 }& t& V1 a2 }4 j W. i+ c/ k 若Maple的计算结果data为集合、矩阵、列表、向量等形式时, 将其写入名为filename的文件时命令格式为: writedata("filename", data);$ O- w4 q: C# g+ H: |* Q
> with(linalg):
7 x' s( X) P9 ?, V$ I( C4 M, { > M:=matrix(3,3,[1,2,3,4,5,6,7,8,9]);
4 Y0 P( W/ S: t+ e- |0 | _. K, D + k" q* A* R0 k
> writedata("e:\\filename.txt",M);7 ~' N6 ^! }) s5 C# N! e
而将结果附加在一个已存在的文件后时,使用命令: writedata[APPEND]("filename", data);
* I3 Q, ?5 `9 P5 Z > W:=matrix(2,2,[1,2,3,4]);
* F7 \+ z: A/ r7 m( a* O4 p
( r1 W* q/ _: v! Z. l% i1 Y > writedata[APPEND]("e:\\filename.txt",W);" r- o1 P# `7 R6 F$ m
需要注意的是, 这里的APPEND是必需的, 否则W结果将会覆盖M结果.8 m. Z/ Y( Z! H; p' A7 k9 ?% \
另外, 若想将结果显示在屏幕上时, 用命令: writedata('terminal', data); n2 J+ j* z: R* h" J% j
> writedata[APPEND]("e:\\filename.txt",W);
- u( p# X. B) Z4 A. u) ] > writedata('terminal',M);# o: A- e* b" J+ B1 g" z: T" s- }
1 2 3
0 `; a. b! C; c, j+ T 4 5 6
9 z6 p$ c9 P1 H- i- F7 s o/ E! P# ` 7 8 9 # G8 D+ G, A f: k4 B/ Y6 I. l
5.1.2 将Maple语句写入一个文件
9 ^! c! n& Q! b, l/ {; m 如果所要写入文件的是表达式、函数的定义或者是一个完整的程序, 则使用命令save, 写入一个或多个语句的命令格式分别如下:
, b# D* {. n4 L1 L save name, "filename";- a; Y1 x9 y8 p: a
save name1, name2, …, "filename";
, _$ i- @9 K% D' \" |$ } 若filename的扩展名为.m, 则Maple会以内定的格式储存, 若扩展名为.txt, 则以纯文本文件储存. 以内定的格式储存的文件作纯文本编辑器无法读取, 但在大多数情况下, 它会比纯文本文件的加载速度更快, 且文件容量小.
, q1 m) W# L" v. x: T [- { > myfunc:=(k,n)->sum(x^k/k!,x=1..n);
- G2 e8 [: A. s
8 m: H8 r: {- X3 @6 X > myresult:=myfunc(6,8);
/ V$ s& J3 s: c & u1 G: e' {8 F1 d& T
> save myfunc,myresult,"e:\\test.m";
. Q3 E* o# Q) ^% \0 {# _ 调用已存m文件用命令read. 试看下述实验:
$ v& z! j- z9 S s$ f > restart:8 F7 t& s; r$ D f
> myfunc(6,8);
% r& I4 y# t& n5 t7 y; ~ 0 a% g9 m7 D5 Q- p$ i
> read "e:\\test.m";
( a( Y& S. |! q$ K > myfunc(6,8);0 S; h. m, S Q- T0 W H
9 s/ L$ o& s+ Y
> myresult;! q/ z# p4 Z5 P$ H9 P$ ?6 n: S8 b
; g4 T1 ]4 M6 ]7 f, a! H 而存为txt文件时则将整个语句存为一个文件:
|& o9 [. ^6 c > save myfunc,myresult,"e:\\test.txt";; A/ k+ k8 }4 R, [2 I, X
> restart: read"e:\\test.txt";
; _! {0 K( \, A# | * n7 e0 W3 T% ~4 d# ?9 x* y1 G
/ V: z: |6 T) _7 M' C. e" w! D \, [' x
5.2 读取文件
3 |8 s- H# W: i3 g) r* a) K 在Maple里最常用的两个读取文件的命令, 一个是读取数值数据, 另一个是是读取Maple的指令.
7 z1 t: f/ @/ g8 v8 e 5.2.1 读取数值数据
4 e( o9 C+ l# ]4 R' q ^ 如果想把大量的数据导入Maple里进行进一步的运算或者要运用大量的实验数据在Maple环境绘图时, 可以用readdata( )命令完成.
) ?* U4 p% E; c, V4 U' g5 Q 从filename文件里读取n行数据时使用命令: readdata("filename",n);
) u' ]7 O& Y d5 Q u; i- y 以指定的格式读取数据时使用命令: readdata("filename",[tyep1,type2,…]);0 v! [/ t- Y' j; T& t* C
> readdata("e:\\filename.txt",3);
) }, R3 Y z) ? ; S8 |5 G' P7 S/ p* d
读取filename的前三列, 第一列为整数形式, 第二、三列为浮点数形式:0 D7 W0 _, G4 b9 R% T, e' w
> readdata("e:\\filename.txt",[integer,float,float]);/ p( P9 [4 X& o6 [4 I& Q
+ r# \% M# ?3 b" A- [; E8 }" d
下面再看一个运用大量的实验数据在Maple环境绘图的实验: ?1 f1 d; _% \1 _; Q/ F* g
> mypts:=[seq([x/1000,cos(x^2/100000)],x=1..1000)]:5 I+ K& A5 k( f& Q
> writedata("e:\\data.txt",evalf(mypts));: [+ N: `9 a, C" b- \5 D/ _% r
> dots:=readdata("e:\\data.txt",100):7 c$ C+ k( w/ {
> nops(dots); w& z0 U/ X- E$ _) u
6 K5 |; f* H' J/ \0 E
> dots[1..4];+ s8 F/ H0 \7 o/ l& {/ n( I
) j- `$ ?9 T0 p! w* [
> plot(dots,style=line);
& J/ ]- V# }4 I* X/ e5 I7 _( J% c
- o- V: L* q& `; g3 @; J 5.2.2 读取Maple的指令
% a& J5 A3 p+ t. a4 m( S) h 在编写程序时, 在普通软件中先编好程序再将其读入Maple环境中常常比直接在Maple中编写更为方便. 如果要将程序代码或Maple指令加载用read命令:6 Q( q$ {) Z; q5 n* {. m( V; E% y% f0 G
read "filename";
# r3 G" E( x1 J! a 如下例:0 L: C! N, o/ f6 f
> reatart:9 r2 l& i; \( o/ u0 z5 ]
> myfunc:=(a::list)->add(i,i=a);/ F9 |* u& G( D- u! }6 H" w
9 u$ S8 [5 f! q/ z
> avg:=(a::list)->myfunc(a)/nops(a);
* f9 F- T n, |; f3 }6 [ 1 F6 Z; `, |) O. f2 }
> save myfunc,avg,"e:\\function.m";
2 R# t; e( w% G! F > restart:* R0 F+ F$ d) K" o1 n# C+ q. {3 Y* u; z
> read "e:\\function.m";# b. A5 ^0 ~+ c/ P* N, R0 F( F
> myfunc([1,2,3,4,5,6,7,8,9]);" ]2 Q& c3 Y0 D1 D
7 t( _9 i" ?# G > avg([1,2,3,4,5,6,7,8,9]);
1 I4 M, H4 C3 w# u* c. B7 _
! w% |) F: N: w C 5.3 与其它程序语言的连接* c6 l( W' r, ~: I/ ~
5.3.1 转换成FORTRAN或C语言4 C4 j8 w- |- X
调用codegen程序包中的fortran命令可以把Maple的结果转换成FORTRAN语言: b! e. S5 l3 W4 @/ {
> with(codegen,fortran):* K6 o, e6 z4 E8 s7 J; N
f:= 1-2*x+3*x^2-2*x^3+x^4;
$ u: {( u! V! }4 w- W0 `2 W ; n9 E. g# R* @% @( l6 N6 h
> fortran(%);
" s* P6 E) H2 Q3 c t0 = 1-2*x+3*x**2-2*x**3+x**4$ f3 r$ T8 u" T! G: Q
> fortran(f,optimized);
; T+ l$ z2 N' B- v0 Y t2 = x**2, ]# A4 n# Y, `/ `$ Z2 L
t6 = t2**2
6 \* z* h" N6 ~9 b5 E t7 = 1-2*x+3*t2-2*t2*x+t62 B$ P5 b, d2 B
> fortran(convert(f,horner,x));
" t- b2 ?% X8 e% L% u/ p: { t0 = 1+(-2+(3+(-2+x)*x)*x)*x9 W9 k5 M& [: n- {
而codegen程序包中的C命令可以把Maple结果转换成C语言格式:, ?! ]% D! R8 d* B `3 b
> with(codegen,C):
3 ]3 i4 E* U4 M! t( S f:=1-x/2+3*x^2-x^3+x^4;0 `: B/ X1 p- `7 g% R5 e
* R" d5 b( ?7 G5 _
> C(f);
0 q2 ?/ j/ O6 I. s/ u S t0 = 1.0-x/2.0+3.0*x*x-x*x*x+x*x*x*x;$ J* s/ V: {! _. N, k
> C(f,optimized);
6 T, T# { k, O' p0 c& m% p t2 = x*x;
5 I. K! ^ C0 O+ V0 ? t5 = t2*t2;& T4 |" f2 ]1 w' k) s
t6 = 1.0-x/2.0+3.0*t2-t2*x+t5;5 @4 I1 u/ F' o; L' ^
optimized命令表示要对转换的表达式进行优化, 如果不加此可选参数, 则直接对表达式进行一一对应的转换.5 S1 B$ d7 z( P6 B8 [
5.3.2 生成LATEX! o# y1 M [3 U9 \
Maple可以把它的表达式转换成LATEX, 使用latex命令即可:0 K/ ]& o5 {- Q) ^; @; O, K! u
> latex(x^2+y^2=z^2);, l8 O2 z7 P) S& n
{x}^{2}+{y}^{2}={z}^{2}
8 j+ i$ `. g; J8 H$ {6 k 还可以将转换结果存为一个文件(LatexFile):, W, K5 J' P, a P9 D- J" V* P/ c
> latex(x^2 + y^2 = z^2, LatexFile);1 M- e7 ]% D' r# h
再如下例:4 e6 O( ^! K/ | D
> latex(Int(1/(x^2+1),x)=int(1/(x^2+1),x)); X6 `- P' h1 O9 I! b
\int \! \left( {x}^{2}+1 \right) ^{-1}{dx}=\arctan\left( x \right)3 m7 g% c" {5 \7 u
7 Q4 g, x* G2 I; c+ G# t- A7 s9 B
zan
总评分: 体力 + 2
查看全部评分