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