第 1 章 - Rlab 科學計算套件

簡介

Node.js 出現之後,JavaScript 得到了快速的發展,Node.js 上的管理套件 npm 所管理的專案數量已經超過百萬個。

雖然這些套件有很多並沒有認真開發,有些只是隨手寫寫,但是好用的套件確實也很多。但是很可惜的是,筆者始終找不到一個完整的《科學計算平台套件》,可以讓我們用 JavaScript 來開發科學計算的程式。

但是、我在 npm 上可以找到《矩陣套件 numeric.js、機率統計套件 jStat.js、符號計算套件 algebrite.js、符號計算套件 algebrite.js、影像處理套件 caman.js 等等好用的科學計算函式庫。

另外也可以找到很多圖表顯示套件,像是 d3.js, c3.js, vis.js 等等。於是我想、我們應該可以用這些套件組合出一個不錯的科學計算套件阿!

既然是程式人,發現了自己需要用的程式並不存在,那麼就只好展現程式人的本色,自己來組合設計一套囉!

於是、 rlab 就誕生了!

安裝與使用

假如您還沒安裝 node.js 開發環境,請立刻到 node.js 的官網 https://nodejs.org/ 上去下載並安裝,然後您就可以使用下列指令安裝 rlab 科學計算套件了!

$ npm install rlab

安裝完成後,您就可以開始撰寫 rlab 套件的 JavaScript 程式了,您只要用 require("rlab") 這個指令將套件匯入到某變數(例如 R ) 當中,就可以開始使用該套件了。

Rlab 套件所支援的函式庫,基本上可以分為《矩陣與線性代數、機率統計、符號運算、微積分與方程式求解》等等。

以下我們針對這些功能,一一用範例展示其用法!

首先讓我們看看《機率模組》的功能,這些功能的語法幾乎都和 R 軟體的函式庫定義方法很類似,如果您學過 R 軟體,那麼應該會很容易的上手。

機率的範例

檔案 : probabilityEx.js

var R = require("rlab");
var dice = R.steps(1,6); // 1..6 點的骰子
log("sample(1:6, 10)", R.samples(dice, 10));  // 投擲十次
log("runif(10,0,1)=", R.runif(10, 0, 1).str());  // 0 到 1 的均等分布抽樣十次。
log("rnorm(10,5,1)=", R.rnorm(10, 5, 1).str());  // 平均值5,標準差 1 的常態分佈 N(5,1) 抽樣十次。
log("dnorm(5,5,1)=", R.dnorm(5, 5, 1)); // 印出 N(5,1) 常態分佈在 5 這點的機率密度函數值。
log("pnorm(5,5,1)=", R.pnorm(5, 5, 1)); // 印出 N(5,1) 常態分佈在 5 這點的累積密度函數值。
log("qnorm(0.5,5,1)=", R.qnorm(0.5, 5, 1)); // 印出 N(5,1) 常態分佈在 50% 時的那一點。
log("rbinom(10, 5, 0.5)=", R.rbinom(10,5,0.5)); // 對投擲五個銅板的二項分布取十個樣本。
log("dbinom(4, 5, 0.5)=", R.dbinom(4,5,0.5)); // 投擲五個銅板恰好有四個成功的機率。
log("dbinom(5, 5, 0.5)=", R.dbinom(5,5,0.5)); // 投擲五個銅板五個都成功的機率。
log("pbinom(4, 5, 0.5)=", R.pbinom(4,5,0.5)); // 投擲五個銅板四個或以下成功的機率。
log("qbinom(0.9, 5, 0.5)=", R.qbinom(0.9,5,0.5)); // 投擲五個銅板累積到幾次成功才能達機率 0.9 呢?

執行結果 :

$ node probabilityEx.js
sample(1:6, 10) [ 3, 5, 3, 2, 3, 3, 1, 2, 4, 3 ] // 模擬隨機投擲十次骰子的結果。
runif(10,0,1)= [0.9119,0.5899,0.6839,0.1350,0.6894,0.9512,0.8186,0.5826,0.4279,0
.5125]  // 0 到 1 的均等分布抽樣十次。 
rnorm(10,5,1)= [5.8961,5.4312,6.0002,5.3623,5.5281,4.4413,6.2144,5.7173,5.3111,1
.3146] // 平均值5,標準差 1 的常態分佈 N(5,1) 抽樣十次。
dnorm(5,5,1)= 0.3989422804014327 // 印出 N(5,1) 常態分佈在 5 這點的機率密度函數值。
pnorm(5,5,1)= 0.5 // 印出 N(5,1) 常態分佈在 5 這點的累積密度函數值。
qnorm(0.5,5,1)= 5 // 印出 N(5,1) 常態分佈在 50% 時的那一點。
rbinom(10, 5, 0.5)= [ 2, 1, 2, 2, 4, 4, 1, 4, 3, 2 ] // 對投擲五個銅板的二項分布取十個樣本。
dbinom(4, 5, 0.5)= 0.15625 // 投擲五個銅板恰好有四個成功的機率。
dbinom(5, 5, 0.5)= 0.03125 // 投擲五個銅板五個都成功的機率。
pbinom(4, 5, 0.5)= 0.96875 // 投擲五個銅板四個或以下成功的機率。
qbinom(0.9, 5, 0.5)= 4 // 投擲五個銅板累積到幾次成功才能達機率 0.9 呢? 答案為 4 次

您可以開一個新的程式檔,直接將上述範例貼進去後執行,就會得到以上的結果!

但是、這些範例在 rlab 專案裡面已經有了,當您安裝完 rlab 之後,會在目前路徑下的 node_modules 資料夾多出一個稱為 rlab 的子資料夾,裡面的 examples 資料夾裡已經有這些範例,您也可以直接切換到該資料夾下執行這些範例,以下是筆者在 windows 8/node.js command prompt 中的執行的過程。

D:\test>npm install rlab
D:\test
`-- [email protected]
  +-- [email protected]
  | `-- [email protected]
  +-- [email protected]
  +-- [email protected]
  +-- [email protected]
  `-- [email protected]

npm WARN enoent ENOENT: no such file or directory, open 'D:\test\package.json'
npm WARN test No description
npm WARN test No repository field.
npm WARN test No README data
npm WARN test No license field.

D:\test>cd node_modules

D:\test\node_modules>dir
 磁碟區 D 中的磁碟是 Data
 磁碟區序號:  9EBE-C367

 D:\test\node_modules 的目錄

2016/09/19  下午 03:00    <DIR>          .
2016/09/19  下午 03:00    <DIR>          ..
2016/09/19  下午 03:00    <DIR>          algebrite
2016/09/19  下午 03:00    <DIR>          big-integer
2016/09/19  下午 03:00    <DIR>          coffeequate
2016/09/19  下午 03:00    <DIR>          jStat
2016/09/19  下午 03:00    <DIR>          lodash
2016/09/19  下午 03:00    <DIR>          numeric
2016/09/19  下午 03:00    <DIR>          rlab
               0 個檔案               0 位元組
               9 個目錄  56,573,394,944 位元組可用

D:\test\node_modules>cd rlab

D:\test\node_modules\rlab>dir
 磁碟區 D 中的磁碟是 Data
 磁碟區序號:  9EBE-C367

 D:\test\node_modules\rlab 的目錄

2016/09/19  下午 03:00    <DIR>          .
2016/09/19  下午 03:00    <DIR>          ..
2016/09/19  下午 03:00               595 .npmignore
2016/09/19  下午 03:00    <DIR>          demo
2016/09/19  下午 03:00    <DIR>          example
2016/09/19  下午 03:00    <DIR>          file
2016/09/19  下午 03:00    <DIR>          img
2016/09/19  下午 03:00    <DIR>          lib
2016/09/19  下午 03:00             1,065 LICENSE
2016/09/19  下午 03:00             2,104 package.json
2016/09/19  下午 03:00    <DIR>          plugin
2016/09/19  下午 03:00             7,323 README.md
2016/09/19  下午 03:00            10,140 rlab.html
2016/09/19  下午 03:00             4,818 rlab.js
2016/09/19  下午 03:00                51 server.js
2016/09/19  下午 03:00               219 setting.json
2016/09/19  下午 03:00    <DIR>          test
2016/09/19  下午 03:00    <DIR>          web
               8 個檔案          26,315 位元組
              10 個目錄  56,573,394,944 位元組可用

D:\test\node_modules\rlab>cd example

D:\test\node_modules\rlab\example>dir
 磁碟區 D 中的磁碟是 Data
 磁碟區序號:  9EBE-C367

 D:\test\node_modules\rlab\example 的目錄

2016/09/19  下午 03:00    <DIR>          .
2016/09/19  下午 03:00    <DIR>          ..
2016/09/19  下午 03:00               253 calculusEx.js
2016/09/19  下午 03:00               484 centralLimitEx.js
2016/09/19  下午 03:00             1,653 matrixEx.js
2016/09/19  下午 03:00               589 probabilityEx.js
2016/09/19  下午 03:00               449 rbmEx.js
2016/09/19  下午 03:00               784 solveEx.js
2016/09/19  下午 03:00               148 splineEx.js
2016/09/19  下午 03:00               624 statisticsEx.js
2016/09/19  下午 03:00             1,288 symbolEx.js
2016/09/19  下午 03:00               782 symbolEx_bak.js
2016/09/19  下午 03:00               164 test.js
2016/09/19  下午 03:00               188 testEx.js
2016/09/19  下午 03:00               180 transformEx.js
              13 個檔案           7,586 位元組
               2 個目錄  56,573,394,944 位元組可用

D:\test\node_modules\rlab\example>node probabilityEx.js
sample(1:6, 10) [ 3, 1, 4, 4, 5, 6, 1, 2, 1, 3 ]
runif(10,0,1)= [0.9813,0.7118,0.6824,0.4958,0.9717,0.2953,0.3978,0.3381,0.2535,0
.4136]
rnorm(10,5,1)= [5.8346,4.9562,3.8783,4.6424,3.3636,4.6152,5.4129,5.4151,4.6590,5
.2606]
dnorm(5,5,1)= 0.3989422804014327
pnorm(5,5,1)= 0.5
qnorm(0.5,5,1)= 5
rbinom(10, 5, 0.5)= [ 5, 2, 4, 2, 1, 2, 4, 2, 4, 3 ]
dbinom(4, 5, 0.5)= 0.15625
dbinom(5, 5, 0.5)= 0.03125
pbinom(4, 5, 0.5)= 0.96875
qbinom(0.9, 5, 0.5)= 4

如果您是使用 git 安裝的話,那麼要執行這些範例會更方便,您可以直接使用下列指令下載並安裝 rlab 專案,然後使用 git clone https://github.com/ccckmit/rlab.git 下載 rlab 專案,再切到 rlab 資料夾下用 npm install 指令安裝相關套件,接著切到 example 資料夾中就可以執行這些範例了。

以下是完整的執行過程:

D:\js>git clone https://github.com/ccckmit/rlab.git
Cloning into 'rlab'...
remote: Counting objects: 410, done.
remote: Compressing objects: 100% (35/35), done.
remote: Total 410 (delta 14), reused 0 (delta 0), pack-reused 373
Receiving objects: 100% (410/410), 1.05 MiB | 238.00 KiB/s, done.
Resolving deltas: 100% (188/188), done.
Checking connectivity... done.

D:\js>cd rlab

D:\js\rlab>dir
 磁碟區 D 中的磁碟是 Data
 磁碟區序號:  9EBE-C367

 D:\js\rlab 的目錄

2016/09/19  下午 03:06    <DIR>          .
2016/09/19  下午 03:06    <DIR>          ..
2016/09/19  下午 03:06               595 .gitignore
2016/09/19  下午 03:06    <DIR>          demo
2016/09/19  下午 03:06    <DIR>          example
2016/09/19  下午 03:06    <DIR>          file
2016/09/19  下午 03:06    <DIR>          img
2016/09/19  下午 03:06    <DIR>          lib
2016/09/19  下午 03:06             1,065 LICENSE
2016/09/19  下午 03:06               821 package.json
2016/09/19  下午 03:06    <DIR>          plugin
2016/09/19  下午 03:06             7,323 README.md
2016/09/19  下午 03:06            10,140 rlab.html
2016/09/19  下午 03:06             4,818 rlab.js
2016/09/19  下午 03:06                51 server.js
2016/09/19  下午 03:06               219 setting.json
2016/09/19  下午 03:06    <DIR>          test
2016/09/19  下午 03:06    <DIR>          web
               8 個檔案          25,032 位元組
              10 個目錄  56,570,593,280 位元組可用


D:\js\rlab>npm install
[email protected] D:\js\rlab
+-- [email protected]
| `-- [email protected]
+-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | `-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | | `-- [email protected]
| | | +-- [email protected]
| | | | `-- [email protected]
| | | |   `-- [email protected]
| | | `-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | +-- [email protected]
| | | | +-- [email protected]
| | | | `-- [email protected]
| | | `-- [email protected]
| | |   `-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | | +-- [email protected]
| | | `-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | | `-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | `-- [email protected]
| | +-- [email protected]
| | | `-- [email protected]
| | |   +-- [email protected]
| | |   `-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| |   `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | | `-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| +-- [email protected]
| +-- [email protected]
| | +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| +-- [email protected]
| | `-- [email protected]
| `-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
`-- [email protected]


D:\js\rlab>cd example

D:\js\rlab\example>node probabilityEx.js
sample(1:6, 10) [ 3, 3, 2, 2, 1, 4, 5, 6, 5, 3 ]
runif(10,0,1)= [0.4753,0.0846,0.3820,0.9451,0.4430,0.9591,0.1376,0.6018,0.5248,
.2652]
rnorm(10,5,1)= [5.1176,4.8671,4.5142,7.8154,5.5630,5.9948,4.8456,3.8672,4.3704,
.8452]
dnorm(5,5,1)= 0.3989422804014327
pnorm(5,5,1)= 0.5
qnorm(0.5,5,1)= 5
rbinom(10, 5, 0.5)= [ 2, 5, 2, 2, 2, 3, 3, 2, 3, 1 ]
dbinom(4, 5, 0.5)= 0.15625
dbinom(5, 5, 0.5)= 0.03125
pbinom(4, 5, 0.5)= 0.96875
qbinom(0.9, 5, 0.5)= 4

統計的範例

接著再讓我們看看統計的範例,像是《平均值、最大最小值、中位數、標準差》等等的函數之使用方式。

檔案 : statisticsEx.js

var R = require("rlab");
var v = [1,3,5];
log("v.max()=", v.max()); // 最大值
log("v.min()=", v.min()); // 最小值
log("v.sum()=", v.sum()); // 總和
log("v.normalize()=", v.normalize()); // 正規化(規一化)
log("v.normalize().sum()=", v.normalize().sum()); // 正規化後的總和。
log("v.product()=", v.product()); // 乘積
log("v.mean()=", v.mean()); // 平均值
log("v.range()=", v.range()); // 範圍
log("v.median()=", v.median()); // 中位數
log("v.variance()=", v.variance()); // 變異數
log("v.sd()=", v.sd(), " sd^2=", v.sd()*v.sd()); // 標準差
log("v.cov(v)=", v.cov(v), "v.cor(v)=", v.cor(v)); // 相關係數
log("factorial(5)=", R.factorial(5)); // 階層 5!

執行 :

$ node statisticsEx.js
v.max()= 5 // 最大值
v.min()= 1 // 最小值
v.sum()= 9 // 總和
v.normalize()= [ 0.1111111111111111, 0.3333333333333333, 0.5555555555555556 ] // 正規化(規一化)
v.normalize().sum()= 1 // 正規化後的總和。
v.product()= 15 // 乘積
v.mean()= 1 // 平均值
v.range()= 4 // 範圍
v.median()= 3 // 中位數
v.variance()= 2.6666666666666665 // 變異數
v.sd()= 1.632993161855452  sd^2= 2.6666666666666665 // 標準差
v.cov(v)= 4 v.cor(v)= 1 // 相關係數
factorial(5)= 120 // 階層 5!

檢定的範例

檔案 : testEx.js

var R = require("rlab");
var v = [1,3,5];

var x = R.rnorm(10, 0, 0.1); // 對 N(0, 0.1) 抽十個樣本
log("x=", x.str()); // 印出來

var t1=R.ttest({x:x, mu:0});
R.report(t1);

執行 :

$ node testEx.js
x= [-0.1405,0.0495,-0.1850,0.0824,0.0687,-0.0854,-0.1049,-0.1171,0.0947,-0.1592]

=========== report ==========
name    : ttest(X)
h       : H0:mu=0
alpha   : 0.0500
op      : =
pvalue  : 0.0003
ci      : [-0.2599,-0.1101]
df      : 9.0000
mean    : -0.1850
sd      : 0.1047

矩陣的範例

為了讓使用者寫起程式來更方便,rlab 將原本 JavaScript 中的陣列物件延伸,讓這些函數盡可能直接採用鏈式語法來撰寫,這樣的程式看起來會更簡潔有力,像是下列程式最後一行的 E.dot(λ.diag()).dot(E.inv()) 就採用了一連串的鏈式語法,這個鏈式語法代表 EλE1E \lambda E^{-1} ,如果採用非鏈式的語法,就會寫成 dot(dot(E, diag(λ)), inv(E)) ,我個人認為鏈式語法還是比較好讀一些的!

以下是《陣列與矩陣運算》的一些例子!

檔案 : matrixEx.js

var M = require("rlab").M;
var v = [1,2,3];
log("v.sin()=", v.sin()); // 對陣列每個元素都取 sin 值
log("v.norm2()=", v.norm2()); // 對陣列取 norm2 (向量長度)
log("v.norm2Squared()=", v.norm2Squared()); // 向量長度的平方

var A = [[1,2,3],[4,5,6],[7,3,9]];
var AiA = A.inv().dot(A); // A的反矩陣 * A
log("AiA=\n", AiA.strM()); // 印出來
log("AiA.tr()=\n", AiA.tr().strM()); // 轉置後印出
log("A=\n", A.str()); // 印出 A
log("A.mul(0.1)=\n", A.mul(0.1).strM()); // 矩陣 A 乘常數 0.1
log("A.row(1)=", A.row(1)); // 取第一列
log("A.col(1)=", A.col(1)); // 取第一行
log("A.sumM()=", A.sumM()); // 取總和
log("A.rowSum()=", A.rowSum()); // 列總和
log("A.colSum()=", A.colSum()); // 行總和
log("A.mean(row)=", A.rowMean().str()); // 列平均
log("A.mean(col)=", A.colMean().str()); // 行平均

var D = M.diag(v); // 對角矩陣
log("D=", D); // 印出

var Eλ = M.eigR(A); // 取特徵值與特徵向量
var E = Eλ.E, λ=Eλ.lambda;
log("E*[λ]*E-1=", E.dot(λ.diag()).dot(E.inv()).strM()); // E*λ*E-1

執行 :

$ node matrixEx.js
v.sin()= [ 0.8414709848078965, 0.9092974268256817, 0.1411200080598672 ]
v.norm2()= 3.7416573867739413
v.norm2Squared()= 14
AiA=
 [[          1,   1.11e-16,  -1.11e-16],
 [          0,          1,  4.441e-16],
 [ -3.331e-16, -3.331e-16,          1]]
AiA.tr()=
 [[          1,          0, -3.331e-16],
 [   1.11e-16,          1, -3.331e-16],
 [  -1.11e-16,  4.441e-16,          1]]
A=
 [[1.0000,2.0000,3.0000],[4.0000,5.0000,6.0000],[7.0000,3.0000,9.0000]]
A.mul(0.1)=
 [[        0.1,        0.2,        0.3],
 [        0.4,        0.5,        0.6],
 [        0.7,        0.3,        0.9]]
A.row(1)= [ 4, 5, 6 ]
A.col(1)= [ 2, 5, 3 ]
A.sumM()= 40
A.rowSum(2)= [ 6, 15, 19 ]
A.colSum(2)= [ 12, 10, 18 ]
A.mean(row)= [2.0000,5.0000,6.3333]
A.mean(col)= [4.0000,3.3333,6.0000]
D= [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]
E*[λ]*E-1= [[          1,          2,          3],
 [          4,          5,          6],
 [          7,          3,          9]]

微積分的範例

檔案 : differentialEx.js

var R = require("rlab");

var d = R.D.d, i=R.D.i, sin=R.sin, PI = R.PI, x2=(x)=>x*x;

log('d(x^2,2)=', d(x2, 2)); // x^2 在 x=2 那點的數值微分
log('d(sin(x/4),pi/4)=', d(sin, PI/4)); // sin(x/4) 在 x=pi/4 的數值微分
log('i(x^2,0,1)=', i(x2,0,1)); // x^2 從 0 到 1 的積分
log('i(sin(x),0,pi/2)=', i(sin,0,PI/2)); // sin(x) 從 0 到 pi/2 的積分

執行 :

D:\Dropbox\github\rlab\example>node differentialEx.js
d(x^2,2)= 4.000999999999699 // x^2 在 x=2 那點的數值微分
d(sin(x/4),pi/4)= 0.7067531099743674 // sin(x/4) 在 x=pi/4 的數值微分
i(x^2,0,1)= 0.33283350000000095 // x^2 從 0 到 1 的積分
i(sin(x),0,pi/2)= 0.9997035898637557 // sin(x) 從 0 到 pi/2 的積分

符號運算

檔案 : symbolEx.js

var R = require("../rlab");
var S = R.Symbol;

print('x+x=', S.run('x + x')) // => 2 x"

print('10!=', S.factor('10!').toString()); // => "2^8 3^4 5^2 7"

print('integral(x^2)=', S.eval('integral(x^2)').toString()); // => "1/3 x^3"

// composing...
print('integral(x)=', S.integral(S.eval('x')).toString()); // => "1/2 x^2"

var questions=[
'13579/99999 + 13580/100000',
'numerator(1/a+1/b)',
'denominator(1/(x-1)/(x-2))',
'rationalize(a/b+b/a)',
'A=1+i;B=sqrt(2)*exp(i*pi/4);A-B',
'simplify(cos(x)^2 + sin(x)^2)',
'simplify(a*b+a*c)',
'simplify(n!/(n+1)!)',
'(x-1)(x-2)^3',
'subst( u, exp(x), 2*exp(x) )',
'roots(3 x + 12 + y = 24)',
'roots(a*x^2+b*x+c)',
'roots(x^4 + x^3 + x^2 + x + 1)',
'roots(m*x^9 + n)',
'roots((x^4+x^3)*(x^4*x^2))',
'nroots(x^4+1)',
'velocity=17000*"mile"/"hr";time=8*"min"/(60*"min"/"hr");velocity/time',
'A=((a,b),(c,d));inv(A);adj(A);det(A);inv(A)-adj(A)/det(A)',
'd(x^2);r=sqrt(x^2+y^2);d(r,(x,y))',
'F=(x+2y,3x+4y);d(F,(x,y))',
'integral(x^2)',
'integral(x*y,x,y)',
];

print("=========== Q&A =============");

for (var i in questions) {
    var q = questions[i];
    print(q, "=", S.run(q.replace(/;/g, '\n')));
}

執行 :

D:\js\rlab\example>node symbolEx.js
x+x= 2 x
10!= 2^8 3^4 5^2 7
integral(x^2)= 1/3 x^3
integral(x)= 1/2 x^2
=========== Q&A =============
13579/99999 + 13580/100000 = 135794321/499995000
numerator(1/a+1/b) = a + b
denominator(1/(x-1)/(x-2)) = x^2 - 3 x + 2
rationalize(a/b+b/a) = (a^2 + b^2) / (a b)
A=1+i;B=sqrt(2)*exp(i*pi/4);A-B = 1 + i - 2^(1/2) exp(1/4 i pi)
simplify(cos(x)^2 + sin(x)^2) = 1
simplify(a*b+a*c) = a (b + c)
simplify(n!/(n+1)!) = 1 / (1 + n)
(x-1)(x-2)^3 = x^4 - 7 x^3 + 18 x^2 - 20 x + 8
subst( u, exp(x), 2*exp(x) ) = 2 u
roots(3 x + 12 + y = 24) = -1/3 y + 4
roots(a*x^2+b*x+c) = (-b / (2 a) - (-4 a c + b^2)^(1/2) / (2 a),-b / (2 a) + (-4
 a c + b^2)^(1/2) / (2 a))
roots(x^4 + x^3 + x^2 + x + 1) = Stop: roots: the polynomial is not factorable,
try nroots
roots(m*x^9 + n) = Stop: roots: the polynomial is not factorable, try nroots
roots((x^4+x^3)*(x^4*x^2)) = (-1,0)
nroots(x^4+1) = (-0.707107 - 0.707107 i,-0.707107 + 0.707107 i,0.707107 + 0.7071
07 i,0.707107 - 0.707107 i)
velocity=17000*"mile"/"hr";time=8*"min"/(60*"min"/"hr");velocity/time = 127500 "
mile" / ("hr"^2)
A=((a,b),(c,d));inv(A);adj(A);det(A);inv(A)-adj(A)/det(A) = ((d / (a d - b c),-b
 / (a d - b c)),(-c / (a d - b c),a / (a d - b c)))
((d,-b),(-c,a))
a d - b c
((0,0),(0,0))
d(x^2);r=sqrt(x^2+y^2);d(r,(x,y)) = 2 x
(x / ((x^2 + y^2)^(1/2)),y / ((x^2 + y^2)^(1/2)))
F=(x+2y,3x+4y);d(F,(x,y)) = ((1,2),(3,4))
integral(x^2) = 1/3 x^3
integral(x*y,x,y) = 1/4 x^2 y^2

網頁版的 rlab

Rlab 不只可以在 node.js 裡面執行,也可以在瀏覽器裡面執行,您只要引用位於 web 資料夾下的 rlab.js 就可以了,以下是一個引用範例。

        <script src="web/rlab.js"></script>        
        <script src="web/glab.js"></script>

如果想使用網頁版的 rlab,那麼可以直接點選 rlab 當中的 rlab.html 打開後直接使用,這個版本可以寫程式與執行,但是該版本由於沒有 server 程式,因此不會有存檔功能。

為了方便您在網頁上使用 rlab 測試程式,特別是那些和圖表有關的程式,我們在 rlab 中放了一個 server 程式,您只要啟動該程式,就可以在網頁上《編輯、測試或儲存》您的程式!

這個 server 使用到筆者的另一個稱為 fdbserver 的套件,您必須安裝該套件後才能啟動該 server,以下是安裝啟動方法。

$ git clone https://github.com/ccckmit/rlab
...
$ cd rlab
...
$ npm install fdbserver
[email protected] D:\Dropbox\github\rlab
+-- [email protected]  extraneous
+-- [email protected]  extraneous
`-- [email protected]  extraneous

$ node server.js

啟動伺服器之後,您只要以 https 模式訪問,也就是在瀏覽器中鍵入 https://localhost/ ,這樣就可以看到下列畫面,這個環境可以讓您編輯 rlab 程式並觀看顯示結果與圖表。

Run rlab on Web

筆者在自己的網站上放了這個 rlab 的展示網頁 http://ccc.nqu.edu.tw/rlab/rlab.html ,您可以點選後使用看看,如果您需要繪製統計表之類的功能,那麼網頁版將會是一個好選擇!

如果您用 https 協定登入,那麼該網站將會有《儲存》(Save File) 的功能,也會有《登入登出》的選項,但如果用 http 模式,或者單純啟動網頁,而不啟動伺服器,那麼就不能編輯存檔!

您必須登入後才能儲存,預設的帳號是 root, 密碼是 123,您可以修改 setting.json 這個檔案改掉帳號密碼,或者新增其他的帳號密碼!

預設的程式儲存位置是在 'file/' 資料夾中,您只要按下儲存就會上傳到該資料夾中。

以上就是 rlab 科學計算環境的基本功能,更詳細的功能我們將在本書後面的章節,一邊教科學計算的方法,一邊用 rlab 進行示範!

results matching ""

    No results matching ""