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