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