演算法

文章推薦指數: 80 %
投票人數:10人

提供maple() 函數讓出題者可呼叫Maple kernel,裡頭用的是Maple 語法,其功能和複雜度就高得多了。

變數. 演算法要做的事就是生成變數並在變數中存入適合的內容,然後把 ... 演算法 概論 在題目中有個部分稱作演算法(Algorithm),可以用來儲存可被MapleT.A.理解的程式碼。

這些程式會在答題者打開題目時執行,執行後再生成題目。

所以在題目生成以後,演算法就不會再執行。

所有題目類型中,只有Maple-graded題目有可能在答題後呼叫Maple程式評分,除此之外就不會有其他執行Maple或MapleT.A.程式的時機了。

使用演算法通常有三個目的,第一個目的是產生可變動的題目。

利用演算法,每次答題者打開題目時,看到的題目都會有變動,無法用背答案的方式作答。

如果用在較為正式的作業或考試,則每位學生的題目可能都不一樣,學生也較不會作弊。

如果是較用功的學生,也可利用這項功能重複練習同一種類型的題目,加深學習印象。

使用演算法的第二個目的是借用Maple的超強功能。

Maple是非常強大的數學軟體,如果是熟練的使用者,可以利用這些功能來達成一般來說不可能自動評分的題目。

更進一步說,如果不能借用Maple,要生成高水準的可變動題目將會非常麻煩,對出題者的程式和數學功力要求會很高。

演算法的第三個用途是展示數學式。

雖然MapleT.A.有提供數學式編輯器編寫數學式,但對於較老練的使用者而言,這種編寫方式有很多缺陷。

如果透過演算法,可以用指令的方式生成數學式圖片並插入文件當中。

如果是亂數生成的函數,就更有必要透過演算法變成較美觀的數學式。

語法規則 請看底下這句話: $foo=maple("randomize():rand()"); 這句話是演算法的一個範例。

演算法中的每一列程式結構都跟這句話一樣,開頭是一個變數放在等號左邊,等號右邊是函數或是算式,句尾要有一個分號(;)。

MapleT.A.提供的演算法並不是很正式的程式語言,每一列程式碼開頭都必須有一個變數來紀錄程式結果,而且MapleT.A.的每個函數一定都會回傳一個運算結果。

MapleT.A.有提供用來代表流程控制的函數,但是沒有迴圈,所以就一個程式語言來說,MapleT.A.是非常容易學習的。

但是如同上面那句話,MapleT.A.提供maple()函數讓出題者可呼叫Maplekernel,裡頭用的是Maple語法,其功能和複雜度就高得多了。

變數 演算法要做的事就是生成變數並在變數中存入適合的內容,然後把變數放入題目的各個部分,如題目敘述、註解或是答案欄,MapleT.A.會把變數轉成變數所代表的內容。

演算法並沒有類似程式語言輸出輸入功能,所謂輸出,就只是把特定內容放入變數,再把變數放到題目或答案中。

而唯一能解讀答題者的輸入只有Maple-graded題目,但這功能就不是演算法提供的。

所以不管在演算法中做過哪些計算,只要沒有將結果存入變數,這些計算就沒有任何意義。

MapleT.A.變數命名規則跟PHP類似,開頭是「$」,然後跟著英文字母和數字。

例如: $num=1; 這段程式碼中$num就是一個變數,程式碼的目的是將數字1存入$num中。

因此在之後的程式碼或是題目敘述等地方,$num會被MapleT.A.視為數字1。

變數在使用前不用事先宣告,想要儲存數字或文字,直接指定就可以了: $a=3; 但是文字必須要用單引號或雙引號包起來: $a='string'; 變數不僅存放數字或文字,也可存放數學式或圖片,這些式子和圖片必須透過MapleT.A.提供的函數生成。

另外,雖然不知道MapleT.A.用哪種方式儲存數學式,但目前MapleT.A.顯示數學式時一定會以圖片方式呈現,所以在使用上數學式跟圖片是一樣的。

此外,MapleT.A.有兩個內建常數─e和pi,e約等於2.71828,pi則是圓週率。

常數不用加$開頭,所以 $a=e; $a大約是2.71828。

另外一個可用在指定變數的語法是科學記號表示法,例如 $a=2.9E8; $a會變成290000000。

運算與數學函數 MapleT.A.可執行四則運算和次方(^)運算,例如: $a=2+3*5^2; 運算後$a等於77。

算子優先順序依序是次方、乘除、加減,如果要改變優先順序,可以用括號把希望優先計算的部分包起來。

除了四則運算,MapleT.A.也提供常見的數學函數: 函數回傳結果範例 abs(x)x的絕對值abs(-3)=2 sqrt(x)x的平方根sqrt(2)=1.414... ln(x)x以e為底的對數ln(e)=1 log(x)x以10為底的對數log(10)=1 exp(x)e的x次方exp(1)=e fact(x)x!fact(4)=24 gcd(x,y)x和y的最大公因數gcd(4,6)=2 frac(x,y)x/y分子分母型式,MathML字串 輸出數學式 請注意上一節介紹的最後一個函數frac(),這個函數並不是數學函數,不執行任何數學運算。

frac()的用途是將x/y變成分子在上分母在下這種較好看的表達形式。

這種表達式據說是以MathML字串儲存,但其實MapleT.A.會將這種字串轉換成圖片,所以存在變數中的就是一張圖片。

在繼續討論前,先簡述MathML。

MathML是W3C提出的標準,指出如何在XML文件中顯示數學式。

透過MathML,網頁中也能呈現過去只有在TeX等文件才能呈現的數學式。

MapleT.A.題目敘述不接受MathML語法,但如果將MathML語法放到變數中,MapleT.A.會將其轉換成圖片後呈現。

另外,用EquationEdit產生的數學式雖然是以圖片呈現,但要是將題目還原成最原始的樣子,就會發現這些數學式也是用MathML編寫的。

MathML表達法分為兩類,一類是意義表達,一類是圖象表達。

圖象表達跟TeX一樣,只要將數學式寫出來就好;而意義表達必須將每個符號意義都說得清清楚楚,因此意義表達的數學式將會非常冗長。

意義表達的好處是用這種方式寫出來的數學式可以很容易送入其它程式中解讀,所以各種後處理(如轉換成語音等)都非常容易。

不過一般來說意義表達實在太過麻煩,所以圖像表達法還是比較常用。

要自己動手寫MathML還是很困難,所以還是利用轉換函數比較實際。

其中一個辦法是呼叫mathml()函數: $bar=mathml("1+2"); mathml()會接受一個字串(用單引號或雙引號包起來),並嘗試解讀字串後轉換成數學式。

如果想要建立更複雜(如包含積分符號)的式子,就必須呼叫Maple提供的MathML()函數。

呼叫Maplekernel 底下是呼叫Maplekernel的例子: $bar=maple("1+2;2*3"); 呼叫Maplekernel的函數是maple(),引數是字串─合法的Maple程式碼。

透過maple()呼叫Maplekernel時,無法用換列字元分開程式碼,但只要每個指令結尾有加分號,程式就可以正確執行。

maple()傳回去的值是送入的程式碼的最後一個輸出結果,上面這個例子有兩個指令,第一個結果是3,第二個結果是6,因為第二個結果是最後一個結果,所以$bar等於6。

如同上一節提到的,Maple也提供建立MathML式子的函數,函數的名字就是MathML()。

底下是一個例子: $ML=maple("MathML[ExportPresentation](a+b)"); 實際上,MathML並不是函數,而是一個Maplepackage,而MathML[ExportPresentation]()才是函數,意思是將輸入的數學式轉換成圖象表達的MathML語法(ExportPresentation)。

這個指令會在變數$ML存入底下這個句子: "a+b" 當然MapleT.A.顯示的是這個句子所代表的圖片。

送到函數中的數學式只要是Maple能接受的數學式就可以了,所以就算是放入像int()(積分函數)這類指令,Maple也能正確的印出積分符號、寫出上下界並給予合適的空間,就這點來說會比MapleT.A.的mathml()來得方便。

但是Maple並不是專門排版的軟體,所以還是有缺陷,底下是一個例子: $ML2=maple("MathML[ExportPresentation](3+5)"); 或許打下這的指令的人希望$ML2存放的是3+5,但是實際上存放的是8─Maple會將能算的都算完後再把不能算的轉換成MathML。

流程控制 MapleT.A.沒有像if...else這種設計,但還是提供了類似的解決方案。

底下指令 $un=if($a,20,30); 如果$a不等於0,則$un是20,反之$un等於30。

要使用流程控制函數,比較函數就很重要了。

MapleT.A.提供下列比較函數: 函數功用 eq($a,$b)$a等於$b回傳1,否則回傳0。

ne($a,$b)$a不等於$b回傳1,否則回傳0。

gt($a,$b)$a大於$b回傳1,否則回傳0。

lt($a,$b)$a小於$b回傳1,否則回傳0。

not($a)$a等於0回傳1,否則回傳0。

亂數產生器 要編寫出有變化的題目,需要利用亂數產生器。

MapleT.A.提供幾個亂數產生器: 函數功用 rint($n)回傳介於0和$n-1的任一整數。

rint($m,$n)回傳介於$m和$n-1的任一整數。

rint($m,$n,$k)回傳$m、$m+$k、$m+2*$k‧‧‧$n-$k中的任一整數。

range($n)回傳介於0和$n的任一整數。

range($m,$n)回傳介於$m和$n的任一整數。

range($m,$n,$k)回傳$m、$m+$k、$m+2*$k‧‧‧$n中的任一整數。

rand($m,$n)回傳介於$m和$n的浮點數。

MapleT.A.提供了switch()函數,用法範例如下: $ans=switch($num,'sin','cos','tan','cot','sec','csc'); 如果$num是0,則$ans會收到字串sin,如果$num是1,則$ans會收到字串cos,依此類推。

通常switch()會和rint()合併使用,比如 $ans=switch(rint(6),'sin','cos','tan','cot','sec','csc'); 能在六個三角函數中隨機選出一個。

這些字串也可以接受中文,筆者看過最無聊的隨機題目只是讓題目中的人名在小明、小強、小華等幾個名字中任選一個‧‧‧。

除了MapleT.A.提供的亂數產生器,出題者也可透過maple()呼叫Maple的亂數函數,未來在其他網頁會介紹其中幾個亂數函數。

由於Maple提供的亂數函數功能非常強大,所以對熟悉Maple的出題者來說,用Maple的亂數函數會比用MapleT.A.的亂數產生器來得方便。

condition cnodition是MapleT.A.唯一一個特殊的指令,這個指令不會產生回傳值,不像if()這種假的流程控制,condition是真正的流程控制(雖然和一般的流程控制截然不同)。

雖然實作細節不明,condition的用途是確保隨機產生的函數不會發生某些情況,例如兩個變數不相等或是某個變數不等於0。

底下是一個範例: $num1=rint(10); $num2=rint(10); condition:ne($num1,$num2); 如果在這段程式碼後沒有再改變$num1和$num2的值,則$num1和$num2可能是從0到9中的任意一個數字,但是這兩個變數絕不可能相等,因為第三列程式會排除這個事件。

Condition後面有一個冒號(:),再後面跟著一個比較函數。

如果比較函數傳回1,則條件通過,程式繼續執行。

也就是說只有Condition:後的條件滿足,程式才能繼續執行。

如果出題者寫了一個永遠不可能滿足的條件,則儲存題目時MapleT.A.就會提出警告。

畫圖 在呼叫maple()時,回傳的都是文字,即使是用MathML產生的數學式,其本質還是文字。

MapleT.A.提供的plotmaple()指令雖然同樣呼叫Maplekernel,但是可以輸入Maple畫圖指令,並將得到的圖片存入變數之中。

底下是一個範例: $plot1=plotmaple("plot(sin(x),x=-10..10)"); 這句話透過plotmaple()呼叫Maple的plot()函數,可以畫出2D圖片。

所以$plot1存放的就是圖片,內容是三角函數sin(x)從-10到10的曲線。

再看底下這個範例: $myplot=plotmaple("plot(sin(x),x=-Pi..Pi),plotdevice='gif',plotoptions='height=250,width=250'"); 這個例子中有三個參數,plotdevice、height和width。

height和width可指定圖片的大小,而plotdevice指定圖片的格式是gif或jpeg。

如果是靜態圖片,使用jpeg就可以了,如果是動態圖片,則要用gif。

Maple可以生成動態圖片,但是筆者從未試過,所以不知道實際上是否真的能用在題目上。

要使用這條指令,建議從這裡複製過去再修改必要的參數。

由於一些奇怪的BUG,目前確定參數中的等號前後加上空白時可能會導致參數失效。

由於演算法只在題目生成以前執行,所以無法寫出可讓答題者在答題前先檢查自己答案的圖形的方法。

但在Maple-graded問題可以在答題後畫圖,讓答題者知道自己的答案會產生什麼圖形。

詳細情況請自行研究。

其它 下表列出一些之前沒提過的函數: 函數功用範例結果 int($num)取出浮點數$num的整數部分。

int(12.34)12 decimal($n,$num)浮點$num四捨五入到小數點下$n位。

decimal(3,12.3456789)12.346 sig($n,$num)浮點$num四捨五入到前$n位。

sig(3,12.3456789)12.3 lsu($n,$num)指出$num第$n位數的基本單位。

lsu(3,12.3456789)0.1 min($n1,$n2,$n3,$n4,...)取最小值。

min(2,3,-1,-2,5,9)-2 max($n1,$n2,$n3,$n4,...)取最大值。

max(2,3,-1,-2,5,9)9 indexof($k,$n1,$n2,$n3,$n4,...)找出序列中第一個$k的位置,如果沒有則傳回-1。

indexof(2,3,-1,2,5,-9,2,3,-2)2 strcat($s1,$s2,$s3,$s4,...)將字串組合起來。

strcat('一','二','三四')'一二三四' 除此之外還有幾個函數沒有在此說明,但可在官方提供的說明手冊中找到。

這些函數大部分都可以透過maple()來達到相同的效果,所以就省略了。

只有java()函數可以用來呼叫出題者的Java程式,但由於這已經遠遠超過這份文件能支援的範圍了,所以請有需要的讀者自行閱讀說明文件。

上一個主題:建立題目 下一個主題:範例和常用函數 首頁



請為這篇文章評分?