查看“Minimal Maxima”的源代码
来自Ubuntu中文
←
Minimal Maxima
跳到导航
跳到搜索
因为以下原因,您没有权限编辑该页面:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
本文作者:Robert Dodier 翻译:dbzhang800 适用版本: 文章状态:整理中... == Maxima 是什么?== Maxima 是一个处理数学表达式的系统,例如x + y, sin(a + bπ)以及u · v − v · u Maxima 并不太关心表达式的含义,一个表达式是否有意义由使用者来判断。 有时你想给未知数赋值并且要计算表达式的值。Maxima 很善长做这件事。但是Maxima 也很 善长推迟赋值;你可以先对表达式做一番处理,然后才给(也许永远不给)未知数赋值。 我们先看几个例子: '''1.我想计算球的体积。''' (%i1) V: 4/3 * %pi * r^3; 3 4 %pi r (%o1) -------- 3 '''2.半径是10。''' (%i2) r: 10; (%o2) 10 '''3.V的值和前面一样;在我们下令以前,Maxima不会改变V的值。''' (%i3) V; 3 4 %pi r (%o3) -------- 3 '''4.Maxima,重新计算一下V。''' (%i4) ’’V; 4000 %pi (%o4) -------- 3 '''5.我想看到一个具体的数值而不是一个表达式。''' (%i5) ’’V, numer; (%o5) 4188.79020478639 == 表达式 == Maxima 中所有的东西都是表达式,包括数学表达式、对象、程序结构等。表达式要么是原子,要么是操作符与它的自变量。 原子是一个符号(名字),一个用引号括起来的字符串,或者是一个数(整数或浮点数)。 所有非原子表达式都表示为op(a1 , . . . , an ),其中op是操作符的名字,a1 , . . . , an 是自变。(表达式的显示形式可能不太一致,但内部表示都是一样的。)表达式中的自变量可以是原子或非原子表达式。 数学表达式中含有一个操作符,比如+ − ∗/ < = > 或者一个函数,比如'''sin'''(x),'''bessel_j'''(n, x)。在这种情况下操作符就是函数。 对象在Maxima 中是表达式。列表[a1 , . . . , an ]就是表达式'''list'''(a1 , . . . , an )。矩阵就是表达式 matrix(list(a1,1 , . . . , a1,n ), . . . ,list(am,1 , . . . , am,n )) 程 序 构 造 是 表 达 式 。 一 个 代 码 块'''block'''(a1 , . . . , an )是 操 作 符 为'''block'''自 变 量 为a1 , . . . , an 的表 达 式 。 条 件 语 句'''if''' a '''then''' b '''elseif''' c '''then''' d是 表 达 式'''if'''(a, b, c, d)。 循 环'''for''' a '''in''' L '''do''' S是 类 似于'''do'''(a, L, S)的表达式。 Maxima 函数'''op'''返回一个非原子表达式的操作符。函数args返回非原子表达式的自变量。函数'''atom'''判断一个表达式是不是原子。 让我们看几个例子。 '''1. 符号、字符串和数字都是原子。为了一次能看到它们,我把几个例子凑到时了一个列表里面。''' (%i2) [a, foo, foo_bar, "Hello, world!", 42, 17.29]; (%o2) [a, foo, foo_bar, Hello, world!, 42, 17.29] '''2. 数学表达式。''' (%i1) [a + b + c, a * b * c, foo = bar, a*b < c*d]; (%o1) [c + b + a, a b c, foo = bar, a b < c d] '''3. 列表和矩阵。列表和矩阵的元可以是任何表达式,甚至是其它列表或矩阵。''' (%i1) L: [a, b, c, %pi, %e, 1729, 1/(a*d - b*c)]; 1 (%o1) [a, b, c, %pi, %e, 1729, ---------] a d - b c (%i2) L2: [a, b, [c, %pi, [%e, 1729], 1/(a*d - b*c)]]; 1 (%o2) [a, b, [c, %pi, [%e, 1729], ---------]] a d - b c (%i3) L [7]; 1 (%o3) --------- a d - b c (%i4) L2 [3]; 1 (%o4) [c, %pi, [%e, 1729], ---------] a d - b c (%i5) M: matrix ([%pi, 17], [29, %e]); [ %pi 17 ] (%o5) [ ] [ 29 %e ] (%i6) M2: matrix([[%pi,17],a*d - b*c],[matrix([1,a],[b,7]),%e]); [ [%pi, 17] a d - b c ] [ ] (%o6) [ [ 1 a ] ] [ [ ] %e ] [ [ b 7 ] ] (%i7) M [2][1]; (%o7) 29 (%i8) M2 [2][1]; [ 1 a ] (%o8) [ ] [ b 7 ] '''4. 程序构造是表达式。x : y表示把y赋给x;这个赋值表达式的值是y。block把几个表达式组合为一个块,然后依次求各个表达式的值;最后一个表达式的值即是块的值。''' (%o1) 25 (%i2) [a, b]; (%o2) [42, 17] (%i3) block ([a], a: 42, a^2 - 1600) + block ([b], b: 5, %pi^b); 5 (%o3) %pi + 164 (%i4) (if a > 1 then %pi else %e) + (if b < 0 then 1/2 else 1/7); 1 (%o4) %pi + - 7 '''5. op返回操作符,args返回自变量,atom判断一个表达式是不是原子。''' (%i1) op (p + q); (%o1) + (%i2) op (p + q > p*q); (%o2) > (%i3) op (sin (p + q)); (%o3) sin (%i4) op (foo (p, q)); (%o4) foo (%i5) op (foo (p, q) := p - q); (%o5) := (%i6) args (p + q); (%o6) [q, p] (%i7) args (p + q > p*q); (%o7) [q + p, p q] (%i8) args (sin (p + q)); (%o8) [q + p] (%i9) args (foo (p, q)); (%o9) [p, - q] (%i10) args (foo (p, q) := p - q); (%o10) [foo(p, q), p - q] (%i11) atom (p); (%o11) true (%i12) atom (p + q); (%o12) false (%i13) atom (sin (p + q)); (%o13) false '''6. 程序构造的操作符和自变量。单引号告诉Maxima构造表达式,但不求值。这点我们后面会涉及。''' (%o0) done (%i1) op ('(block ([a], a: 42, a^2 - 1600))); (%o1) block (%i2) op (' (if p > q then p else q)); (%o2) if (%i3) op ('(for x in L do print (x))); (%o3) mdoin (%i4) args (' (block ([a], a: 42, a^2 -1600))); 2 (%o4) [[a], a : 42, a - 1600] (%i5) args (' (if p > q then p else q)); (%o5) [p > q, p, true, q] (%i6) args (' (for x in L do print (x))); (%o6) [x, L, false, false, false, false, print(x)] ==求值== 一个符号的值是跟这个符号相关联的一个表达式。每个符号都有一个值如果没有被赋值,一个符号的值就是它自己。(例如,如果没有给x赋过值,那么它的值就是x。)数字和字符串的值就是它们本身。 一个非原子表达式基本上按下面方式求值。 # 对表达式中操作符的每一个自变量求值。 # 如果一个操作符是一个可以调用的函数,那么就调用这个函数,而表达式的值就是该函数 的返回值。 在几种情况下,上述求值过程会发生变化。其中一些变化将导致较少的求值运算: # 有一些函数并不对它们一部分或者全部自变量进行求值,或者相反修改了它们自变量的值。 # 一个单引号 会阻止求值。 ## 'a的求值结果为a。a的任何其它值都被忽略掉。 ## 对 f (a1, ..., an )的求值得到时f (ev(a1), ..., ev(an))。也就是说,自变量都被求值了,而f 却没有被调用。 ## '(...)将阻止(...)中任何表达式的求值。 另外一些变化会导致更多的求值运算。 # 两个单引号 a使得在对表达式a作语法分析的时候就额外求值一次。 # '''ev(a)'''使得每次对'''ev'''(a)求值的时候都额外对a求值。 # '''apply'''(f, [a1, ..., an ])将会对自变量(a1, ..., an )求值,即使f 只是一般地引用它们。 # '''define'''像:= 一样构造一个函数定义,但是'''define'''会对函数体求值而:=则仅仅引用函数体。 下面看一些表达式是怎样被求值的。 '''1. 如果没有被赋值,那么符号的求值结果就是它们自身。''' (%i1) block (a: 1, b: 2, e: 5); (%o1) 5 (%i2) [a, b, c, d, e]; (%o2) [1, 2, c, d, 5] '''2. 操作符的自变量一般求值(除非以某种方法阻止求值)。''' (%i1) block (x: %pi, y: %e); (%o1) %e (%i2) sin (x + y); (%o2) - sin(%e) (%i3) x > y; (%o3) %pi > %e (%i4) x!; (%o4) %pi! '''3. 如果操作符对应于一个可调用函数,那么调用这个函数(除非被阻止)。否则,求值会得到具有同一个操作符的另一个表达式。''' (%i1) foo (p, q) := p - q; (%o1) foo(p, q) := p - q (%i2) p: %phi; (%o2) %phi (%i3) foo (p, q); (%o3) %phi - q (%i4) bar (p, q); (%o4) bar(%phi, q) '''4. 一些函数引用它们的自变量。例如:save , :=, kill''' '''5. 一个单引号会阻止求值。''' '''6. 两个单引号使得在对表达式作语法分析的时候就额外求值一次。''' '''7. ev使得每当它求值的时候才有一次额外的求值。请对比它与两个单引号的不同效果。''' '''8. apply导致对自变量求值,即便通常情况下仅仅对它们引用。''' '''9. define对函数定义求值。''' ==化简== ==apply,map和lambda== ==内置对象类型== ==如何. . .== ==Maxima 编程== Maxima有一个包含了全部Maxima符号的命名空间。没有办法建立其它命名空间。 所有变量都是全局的,除非它们出现在局部变量的声明中。函数、lambda表达式、以及块中可以有局部变量。 一个变量的值总是最近一次赋值给它的那个,要么通过显式赋值,要么是通过对块、函数、或者lambda表达式中的局部变量赋值。这个策略称为动态域。 如果一个变量是函数、lambda表达式、或者块中的局部变量,它的值是局部的,但它的其它属性(象由'''declare'''建立的)是全局的。函数'''local'''把一个变量的全部属性变为局部的。 一个函数定义默认是全局的,即便它出现在函数、lambda表达式、或者块中。local(f),f(x):=...产生一个局部函数定义。 '''trace'''(foo)会让Maxima在进入和退出函数foo时打印一条消息。 下面看一些Maxima编程的例子。 '''1. 所有变量都是全局的,除非它们出现在局部变量的声明中。函数、lambda表达式、以及块中可以有局部变量。''' (%i1) (x: 42, y:1729, z:foo*bar); (%o1) bar foo (%i2) f(x, y) := x * y * z; (%o2) f(x, y) := x y z (%i3) f(aa, bb); (%o3) aa bar bb foo (%i4) lambda([x, z], (x - z)/y); x - z (%o4) lambda([x, z], -----) y (%i5) apply(%, [uu, vv]); uu - vv (%o5) ------- 1729 (%i6) block([y, z], y: 65536, [x, y, z]); (%o6) [42, 65536, z] (%i7) '''2. 一个变量的值总是最近一次赋给它的那个,要么通过显式赋值,要么是通过对块、函数、或者lambda表达式中的局部变量赋值。''' (%i1) foo(y) := x - y; (%o1) foo(y) := x - y (%i2) x: 1729; (%o2) 1729 (%i3) foo(%pi); (%o3) 1729 - %pi (%i4) bar(x) := foo(%e); (%o4) bar(x) := foo(%e) (%i5) bar(42); (%o5) 42 - %e (%i6) ==Lisp 和Maxima== 构造 ''':lisp''' expr告诉Lisp解释器去计算expr。这个构造可以在命令提示符中被识别,也可以 在'''batch'''而不是'''load'''处理的文件中被识别。 Maxima的符号'''foo'''对应于Lisp中的符号$foo,Lisp中的符号foo对应于Maxima中的符号?'''foo''' 。 ''':lisp''' ('''defun''' $foo(a)(. . .)定义了一个计算它的参数的Lisp函数。在Maxima中,这个函数通过'''foo'''(a)被调用。 ''':lisp''' ('''defmspec''' $foo(e)(. . .)定义了一个引用它的参数的Lisp函数。在Maxima中,这个函数通过'''foo'''(a)被调用。$foo的参数是('''cdr''' e),而且('''caar''' e)总是$foo自身。 在Lisp中,构造('''mfuncall''' ’$foo a1 . . . an ) 调用Maxima中定义的foo函数。 下面让我们从Maxima进入Lisp,或者反过来说。 '''1. 构造:lisp expr告诉Lisp解释器去计算expr。''' (%i1) (aa + bb)^2; 2 (%o1) (bb + aa) (%i2) :lisp $% ((MEXPT SIMP) ((MPLUS SIMP) $AA $BB) 2) '''2. :lisp (defun $foo(a)(. . .)定义了一个计算它的参数的Lisp函数foo。''' (%i1) :lisp (defun $foo (a b) ‘((mplus) ((mtimes) ,a ,b) $%pi)) $FOO (%i1) (p: x + y, q: x - y); (%o1) x - y (%i2) foo (p, q); (%o2) (x - y) (y + x) + %pi '''3. :lisp (defmspec $foo(e)(. . .)定义了一个引用它的参数的Lisp函数foo。''' (%i1) :lisp(defmspec $bar(e)(let((a(cdr e)))‘((mplus)((mtimes),@a) #<CLOSURE LAMBDA(E)(LET((A(CDR E)))‘((MPLUS)((MTIMES),@A)$%PI))> (%i1) bar (p, q); (%o1) p q + %pi (%i2) bar (’’p, ’’q); (%o2) p q + %pi '''4. 在Lisp中,构造(mfuncall ’$foo a1 . . . an ) 调用Maxima中定义的foo函数。''' (%i1) blurf (x) := x^2; 2 (%o1) blurf(x) := x (%i2) :lisp (displa (mfuncall '$blurf' ((mplus) $grotz $mumble))) 2 (mumble + grotz) NIL
返回
Minimal Maxima
。
导航菜单
页面操作
页面
讨论
阅读
查看源代码
历史
页面操作
页面
讨论
更多
工具
个人工具
登录
导航
首页
最近更改
随机页面
页面分类
帮助
搜索
编辑
编辑指南
沙盒
新闻动态
字词处理
工具
链入页面
相关更改
特殊页面
页面信息