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