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