├── source ├── video.md ├── code.md ├── people.md ├── science.md ├── article.md ├── hardware.md ├── preface.md ├── software.md ├── pdffooter.htm ├── focus.md ├── md0.js ├── Makefile ├── convert.exe ├── mimetex.exe ├── tex2img.bat ├── title.md ├── metadata.xml ├── editor.md ├── header.htm ├── footer.htm ├── license.md ├── reflink.md9 ├── article5.md ├── focus1.md ├── article2.md ├── home.md ├── article6.md ├── info.md ├── article1.md ├── article7.md ├── article4.md ├── focus3.md ├── article3.md ├── focus4.md └── focus2.md ├── img ├── R.jpg ├── JsLab.jpg ├── Octave.jpg ├── SciPy.jpg ├── azure1.jpg ├── azure2.jpg ├── azure3.jpg ├── azure4.jpg ├── azure5.jpg ├── azure6.jpg ├── azure7.jpg ├── azure8.jpg ├── cover.jpg ├── vis3D.jpg ├── visNet.jpg ├── c3chart.jpg ├── coverA4.png ├── JsLabCurve.jpg ├── JsLabHist.jpg ├── JsLabPlot.jpg ├── jsLabC3Graph.jpg ├── JsLabIntelliSense.jpg └── CodeMirrorJsComplete.jpg ├── book ├── A4.pdf ├── A4.epub ├── ipad.epub └── ipad.pdf ├── submit └── 利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites.doc ├── README.md ├── htm ├── code.html ├── hardware.html ├── people.html ├── science.html ├── software.html ├── preface.html ├── video.html ├── article.html ├── discuss.html ├── video1.html ├── focus.html ├── title.html ├── editor.html ├── license.html ├── article5.html ├── focus1.html ├── discuss1.html ├── home.html ├── article6.html ├── info.html ├── article2.html ├── article1.html ├── article7.html ├── article4.html ├── focus3.html ├── article3.html ├── focus4.html └── focus2.html └── css └── pmag.css /source/video.md: -------------------------------------------------------------------------------- 1 | # 影音頻道 2 | -------------------------------------------------------------------------------- /source/code.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/people.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/science.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/article.md: -------------------------------------------------------------------------------- 1 | # 程式人文集 2 | 3 | -------------------------------------------------------------------------------- /source/hardware.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/preface.md: -------------------------------------------------------------------------------- 1 | # 前言 2 | 3 | 4 | -------------------------------------------------------------------------------- /source/software.md: -------------------------------------------------------------------------------- 1 | 2 | # 影音頻道 3 | -------------------------------------------------------------------------------- /source/pdffooter.htm: -------------------------------------------------------------------------------- 1 |
_PAGENUM_
2 | -------------------------------------------------------------------------------- /source/focus.md: -------------------------------------------------------------------------------- 1 | # 本期焦點:JsLab -- JavaScript 版的科學計算平台 2 | -------------------------------------------------------------------------------- /img/R.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/R.jpg -------------------------------------------------------------------------------- /book/A4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/book/A4.pdf -------------------------------------------------------------------------------- /book/A4.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/book/A4.epub -------------------------------------------------------------------------------- /book/ipad.epub: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/book/ipad.epub -------------------------------------------------------------------------------- /book/ipad.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/book/ipad.pdf -------------------------------------------------------------------------------- /img/JsLab.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/JsLab.jpg -------------------------------------------------------------------------------- /img/Octave.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/Octave.jpg -------------------------------------------------------------------------------- /img/SciPy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/SciPy.jpg -------------------------------------------------------------------------------- /img/azure1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure1.jpg -------------------------------------------------------------------------------- /img/azure2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure2.jpg -------------------------------------------------------------------------------- /img/azure3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure3.jpg -------------------------------------------------------------------------------- /img/azure4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure4.jpg -------------------------------------------------------------------------------- /img/azure5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure5.jpg -------------------------------------------------------------------------------- /img/azure6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure6.jpg -------------------------------------------------------------------------------- /img/azure7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure7.jpg -------------------------------------------------------------------------------- /img/azure8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/azure8.jpg -------------------------------------------------------------------------------- /img/cover.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/cover.jpg -------------------------------------------------------------------------------- /img/vis3D.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/vis3D.jpg -------------------------------------------------------------------------------- /img/visNet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/visNet.jpg -------------------------------------------------------------------------------- /source/md0.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/source/md0.js -------------------------------------------------------------------------------- /img/c3chart.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/c3chart.jpg -------------------------------------------------------------------------------- /img/coverA4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/coverA4.png -------------------------------------------------------------------------------- /source/Makefile: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/source/Makefile -------------------------------------------------------------------------------- /img/JsLabCurve.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/JsLabCurve.jpg -------------------------------------------------------------------------------- /img/JsLabHist.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/JsLabHist.jpg -------------------------------------------------------------------------------- /img/JsLabPlot.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/JsLabPlot.jpg -------------------------------------------------------------------------------- /source/convert.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/source/convert.exe -------------------------------------------------------------------------------- /source/mimetex.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/source/mimetex.exe -------------------------------------------------------------------------------- /img/jsLabC3Graph.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/jsLabC3Graph.jpg -------------------------------------------------------------------------------- /img/JsLabIntelliSense.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/JsLabIntelliSense.jpg -------------------------------------------------------------------------------- /img/CodeMirrorJsComplete.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/img/CodeMirrorJsComplete.jpg -------------------------------------------------------------------------------- /source/tex2img.bat: -------------------------------------------------------------------------------- 1 | if not exist {%2.jpg} ( 2 | mimetex -d %1 -e %2.gif 3 | convert %2.gif %2.jpg 4 | rm %2.gif 5 | ) 6 | -------------------------------------------------------------------------------- /source/title.md: -------------------------------------------------------------------------------- 1 | % [程式人雜誌](http://programmermagazine.github.com/home/) 2 | % 2014 年 11 月 3 | % 本期焦點:JsLab - JavaScript 版的科學計算平台 4 | -------------------------------------------------------------------------------- /source/metadata.xml: -------------------------------------------------------------------------------- 1 | Creative Commons Non-Commercial Share Alike 3.0 2 | en-US 3 | -------------------------------------------------------------------------------- /submit/利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/programmermagazine/201411/gh-pages/submit/利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites.doc -------------------------------------------------------------------------------- /source/editor.md: -------------------------------------------------------------------------------- 1 | ## 編輯小語 2 | 3 | 本期的「程式人雜誌」探討的焦點是我在建構 JsLab 這個「JavaScript 的科學計算平台」上所採用的開放原始碼專案,以及建構這個專案過程中所學到的一些經驗與心得,透過這樣的心得分享,或許可以讓「程式人」對科學計算與開放原始碼的使用有更多的瞭解也說不定。 4 | 5 | ---- (「程式人雜誌」編輯 - 陳鍾誠) 6 | -------------------------------------------------------------------------------- /source/header.htm: -------------------------------------------------------------------------------- 1 |
2 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

3 |
4 |
5 | -------------------------------------------------------------------------------- /source/footer.htm: -------------------------------------------------------------------------------- 1 |
2 | 5 | -------------------------------------------------------------------------------- /source/license.md: -------------------------------------------------------------------------------- 1 | ## 授權聲明 2 | 3 | 本雜誌許多資料修改自維基百科,採用 創作共用:[姓名標示、相同方式分享] 授權,若您想要修改本書產生衍生著作時,至少應該遵守下列授權條件: 4 | 5 | 1. 標示原作者姓名 (包含該文章作者,若有來自維基百科的部份也請一併標示)。 6 | 3. 採用 創作共用:[姓名標示、相同方式分享] 的方式公開衍生著作。 7 | 8 | 另外、當本雜誌中有文章或素材並非採用 [姓名標示、相同方式分享] 時,將會在該文章或素材後面標示其授權,此時該文章將以該標示的方式授權釋出,請修改者注意這些授權標示,以避免產生侵權糾紛。 9 | 10 | 例如有些文章可能不希望被作為「商業性使用」,此時就可能會採用創作共用:[姓名標示、非商業性、相同方式分享] 的授權,此時您就不應當將該文章用於商業用途上。 11 | 12 | 最後、懇請勿移除公益捐贈的相關描述,以便讓愛心得以持續散播! 13 | 14 | -------------------------------------------------------------------------------- /source/reflink.md9: -------------------------------------------------------------------------------- 1 | [程式人雜誌社團]: https://www.facebook.com/groups/programmerMagazine/ 2 | [科學玩具實驗室]:https://www.facebook.com/groups/sciencetoy/ 3 | [姓名標示、相同方式分享]: http://creativecommons.org/licenses/by-sa/3.0/tw/ 4 | [姓名標示、非商業性、相同方式分享]: http://creativecommons.org/licenses/by-nc-sa/3.0/tw/ 5 | [馬萬圳]: http://coopermaa2nd.blogspot.tw/ 6 | [陳鍾誠]: http://ccckmit.wikidot.com/ 7 | [雜誌訂閱]: https://docs.google.com/spreadsheet/viewform?fromEmail=true&formkey=dG1TcER6Q3h1ZkpacFpDeEVFTDBLeVE6MQ 8 | [College Physics]:http://openstaxcollege.org/textbooks/college-physics 9 | [維基百科]:http://zh.wikipedia.org/ -------------------------------------------------------------------------------- /source/article5.md: -------------------------------------------------------------------------------- 1 | ## Memory Sanitization (作者:研發養成所 Bridan) 2 | 3 | 什麼叫記憶體衛生處理?讓我們先看個故事再做說明。 4 | 5 | 阿誠是某高科技公司的工程師,他負責 6 | 使用儀器量測新產品實驗數據,有位同事阿堅和他很要好,常常去實驗室找他聊天,其實阿堅是另一家公司派來長期臥底的間諜,專門探詢公司最新研發的產品。公司有一台極輕巧的溫度監控儀,阿誠常使用它對新產品零件溫度監控,實驗完畢後,資料當然改存到電腦中,並且依據儀器說明書上,資料清除步驟清資料。一天阿堅向阿誠借用這儀器,其實他是把儀器拿給儀器駭客進行逆向工程,去解碼原始實驗資料。 7 | 8 | 從這故事,你學到了什麼?有許多科技公司對資訊安全非常在意,連清理資料也要徹底破壞! 9 | 10 | 大家都知道在 *電腦上刪除檔案,只不過是把檔案搬移到資源回收筒,隨時可以檔案還原,稍微注意的人,還會清除資源回收筒的檔案,更高竿的會再進行衛生處理,徹底洗掉不要的資料。* 11 | 12 | 一般資料庫,清除資料的做法是破壞資料索引,簡單的說,利用一個索引指示有多少資料在資料庫中,如果索引為N,表示有N筆資料在其中,使用者可以循序用指令將資料取出。當索引為零時,也表示資料庫資料清除。這方法雖然快速簡單,可是欠缺資料安全性,為避免上述事件發生,除了一般清除,還要另外設計徹底清除功能。換個例子說明,也就是上完廁所,除了擦屁股,沖水之外,不要忘記馬桶順便刷一刷洗一洗,徹底做個衛生處理。 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 關於程式人雜誌 2 | 3 | [程式人雜誌] 是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌。 4 | 5 | ## 授權聲明 6 | 7 | 本雜誌許多資料修改自維基百科,採用 創作共用:[姓名標示、相同方式分享] 授權,若您想要修改本書產生衍生著作時,至少應該遵守下列授權條件: 8 | 9 | 1. 標示原作者姓名 (包含該文章作者,若有來自維基百科的部份也請一併標示)。 10 | 3. 採用 創作共用:[姓名標示、相同方式分享] 的方式公開衍生著作。 11 | 12 | 另外、當本雜誌中有文章或素材並非採用 [姓名標示、相同方式分享] 時,將會在該文章或素材後面標示其授權,此時該文章將以該標示的方式授權釋出,請修改者注意這些授權標示,以避免產生侵權糾紛。 13 | 14 | 例如有些文章可能不希望被作為「商業性使用」,此時就可能會採用創作共用:[姓名標示、非商業性、相同方式分享] 的授權,此時您就不應當將該文章用於商業用途上。 15 | 16 | 最後、懇請勿移除公益捐贈的相關描述,以便讓愛心得以持續散播! 17 | 18 | 19 | [程式人雜誌]: https://www.facebook.com/groups/programmerMagazine/ 20 | [姓名標示、相同方式分享]: http://creativecommons.org/licenses/by-sa/3.0/tw/ 21 | [姓名標示、非商業性、相同方式分享]: http://creativecommons.org/licenses/by-nc-sa/3.0/tw/ 22 | -------------------------------------------------------------------------------- /source/focus1.md: -------------------------------------------------------------------------------- 1 | ## 科學計算軟體簡介 2 | 3 | 很多人都曾經使用過「科學計算軟體」,特別是對於進行學術研究的人員而言,這些軟體可以說是不可或缺的。 4 | 5 | 在工程領域,最常被使用的科學計算軟體是 MatLab,這個軟體從「矩陣運算」出發,建構出了龐大的函式庫,讓使用者可以輕易的透過 Matlab 進行電腦實驗。 6 | 7 | 另外、在社會科學與統計學領域,很多人會用 SPSS、SAS 等軟體做統計分析,這兩個軟體是從統計出發的科學計算工具。 8 | 9 | 事實上、開放原始碼領域也有對應的科學計算軟體,像是 R 與 Octave 都是 Open Source 的科學計算軟體。 10 | 11 | ![圖、Octave 軟體的官方網站](../img/Octave.jpg) 12 | 13 | R 與 SPSS、SAS 的出發點較類似,是從機率統計領域開始建構的,而 Octave 則完全模仿 Matlab 的語法,試圖建構一個與 Matlab 語言相容的科學計算平台,讓 Matlab 的程式資源也可以被 Octave 社群所使用。 14 | 15 | ![圖、R 軟體的官方網站](../img/R.jpg) 16 | 17 | 在開源的科學計算軟體中, [R 軟體](http://www.r-project.org/) 的使用者似乎是最多的,但是由於 R 採用的程式語言 S3 並非 OpenSource 程式領域的主流,因此也有人試圖用 Python 等語言去建構出科學計算的環境,像是 [SciPy](http://www.scipy.org/) 就整合了 numpy 、sympy、Matplotlib、 18 | 19 | ![圖、SciPy 的官方網站](../img/SciPy.jpg) 20 | 21 | 雖然已經有了這麼多開放原始碼的科學計算軟體,而且我本身也是 R 的使用者,但是、我仍然感到遺憾! 22 | 23 | 因為我沒辦法找到建構在 JavaScript 語言上的科學計算軟體,所以、我打算自己建造一個,這個計劃就稱為 JsLab (JavaScript Laboratory)。 24 | 25 | 在下列文章中,我將介紹自己為何要建構 JsLab 專案,如何建構 JsLab 專案,並與大家分享我在建構 JsLab 專案時所學到的一些經驗與心得。 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/code.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

# 影音頻道

17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htm/hardware.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

# 影音頻道

17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htm/people.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

# 影音頻道

17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htm/science.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

# 影音頻道

17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htm/software.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

# 影音頻道

17 |
18 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /htm/preface.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

前言

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/video.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

影音頻道

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/article.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

程式人文集

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/discuss.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 9 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

程式人討論區

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/video1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 9 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

看影片學 FPGA 設計

22 |
23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /source/article2.md: -------------------------------------------------------------------------------- 1 | ## c3.js -- 基於 d3.js 的簡易繪圖框架 2 | 3 | 雖然 d3.js 很強大,但是卻並不容易使用,如果我們只是要畫一些簡易的圖形,可以採用延伸自 d3.js 的 c3.js 。 4 | 5 | C3.js 的使用非常的簡單,而且互動性很強大。舉例而言,以下是 C3.js 的一個範例,您將滑鼠游標移到圖形上,會顯示對應軸線的資料表格,這讓使用者可以很清楚的看到圖形所對應的數據,這是非常具有互動性的顯示方式。 6 | 7 | ![圖、C3.js 的一個繪圖範例](../img/c3chart.jpg) 8 | 9 | 您可以點選下列網址試試看這個範例,應該可以感覺到 C3.js 好用的地方。 10 | 11 | * 12 | 13 | 而且、要產生上述的圖形,也只需要短短幾行簡單的資料與程式,其程式碼如下所示: 14 | 15 | ```javascript 16 | var chart = c3.generate({ 17 | data: { 18 | columns: [ 19 | ['data1', 30, 20, 50, 40, 60, 50], 20 | ['data2', 200, 130, 90, 240, 130, 220], 21 | ['data3', 300, 200, 160, 400, 250, 250], 22 | ['data4', 200, 130, 90, 240, 130, 220], 23 | ['data5', 130, 120, 150, 140, 160, 150], 24 | ['data6', 90, 70, 20, 50, 60, 120], 25 | ], 26 | type: 'bar', 27 | types: { 28 | data3: 'spline', 29 | data4: 'line', 30 | data6: 'area', 31 | }, 32 | groups: [ 33 | ['data1','data2'] 34 | ] 35 | } 36 | }); 37 | ``` 38 | 39 | 從以上的範例中,您應該可以看到 C3 這個架構的優點,相較於 D3 而言, C3 容易使用多了。 40 | 41 | 但是、 C3 並沒有辦法完全發揮 D3 的功能,像是筆者就沒看到 C3 具有任何可以繪製統計 box chart 的功能,因此對於某些較少見的情況而言,我們還是得直接採用 D3 ,另外 C3 的文件說明並不完整,這是筆者所看到的 C3 框架之缺陷。 42 | 43 | ### 參考文獻 44 | * 45 | -------------------------------------------------------------------------------- /htm/focus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /htm/title.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 程式人雜誌 9 | 10 | 11 | 12 | 13 |
14 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

15 |
16 |
17 | 22 | 23 |
24 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /htm/editor.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

編輯小語

22 |

本期的「程式人雜誌」探討的焦點是我在建構 JsLab 這個「JavaScript 的科學計算平台」上所採用的開放原始碼專案,以及建構這個專案過程中所學到的一些經驗與心得,透過這樣的心得分享,或許可以讓「程式人」對科學計算與開放原始碼的使用有更多的瞭解也說不定。

23 |

---- (「程式人雜誌」編輯 - 陳鍾誠)

24 |
25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /source/home.md: -------------------------------------------------------------------------------- 1 | ### 關於程式人雜誌 2 | 3 | 程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌。 4 | 5 | ### 雜誌下載 6 | 7 | 出刊年月 epub ipad:PDF A4:PDF 單頁 HTM 全部下載 8 | ------------ ---------- ----------- -------- ----------- ------------- 9 | 2014年11月 [epub] [ipad.pdf] [A4.pdf] [pmag.html] [github] 10 | 11 | ### 本期內容 12 | * 前言 13 | * [編輯小語](editor.html) 14 | * [授權聲明](license.html) 15 | * 本期焦點:JsLab -- JavaScript 版的科學計算平台 16 | * [科學計算軟體簡介](focus1.html) 17 | * [JsLab -- JavaScript 版的科學計算平台](focus2.html) 18 | * [「JsLab 科學計算平台」背後的開放原始碼結構](focus3.html) 19 | * [R.js -- 從 jStat 延伸出的開源 JavaScript 機率統計框架](focus4.html) 20 | * 程式人文集 21 | * [d3.js -- 互動式繪圖框架](article1.html) 22 | * [c3.js -- 基於 d3.js 的簡易繪圖框架](article2.html) 23 | * [Vis.js -- 另一個強大的 JavaScript 繪圖函式庫](article3.html) 24 | * [CodeMirror -- 有 IntelliSense 功能的網頁版開源編輯器](article4.html) 25 | * [Memory Sanitization (作者:研發養成所 Bridan)](article5.html) 26 | * [利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites (作者:陳星銘)](article6.html) 27 | * [函數指標陣列 (Array of Function Pointers) (作者:研發養成所 Bridan)](article7.html) 28 | * [雜誌訊息](info.html) 29 | 30 | ### 雜誌取得 31 | 32 | 程式人雜誌預定於每個月 1 日出刊,您可以從下列網址取得程式人雜誌的所有內容 (包含當月最新出刊的雜誌)。 33 | 34 | * 35 | 36 | ### 連絡我們 37 | 38 | 竭誠歡迎程式人投稿,或者成為本雜誌的專欄作家,現在就可以加入 [程式人雜誌社團] 一同共襄盛舉。 39 | 40 | 本雜誌編輯為「陳鍾誠 (@ccckmit)」,若要聯絡編輯,請寄信到 。 41 | 42 | [epub]: ../book/A4.epub 43 | [ipad.pdf]: ../book/ipad.pdf 44 | [A4.pdf]: ../book/A4.pdf 45 | [code.zip]: ../code.zip 46 | [pmag.html]: ../book/pmag.html 47 | [github]: https://github.com/programmermagazine/201411 48 | 49 | -------------------------------------------------------------------------------- /htm/license.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

授權聲明

22 |

本雜誌許多資料修改自維基百科,採用 創作共用:姓名標示、相同方式分享 授權,若您想要修改本書產生衍生著作時,至少應該遵守下列授權條件:

23 |
    24 |
  1. 標示原作者姓名 (包含該文章作者,若有來自維基百科的部份也請一併標示)。
  2. 25 |
  3. 採用 創作共用:姓名標示、相同方式分享 的方式公開衍生著作。
  4. 26 |
27 |

另外、當本雜誌中有文章或素材並非採用 姓名標示、相同方式分享 時,將會在該文章或素材後面標示其授權,此時該文章將以該標示的方式授權釋出,請修改者注意這些授權標示,以避免產生侵權糾紛。

28 |

例如有些文章可能不希望被作為「商業性使用」,此時就可能會採用創作共用:姓名標示、非商業性、相同方式分享 的授權,此時您就不應當將該文章用於商業用途上。

29 |

最後、懇請勿移除公益捐贈的相關描述,以便讓愛心得以持續散播!

30 |
31 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /source/article6.md: -------------------------------------------------------------------------------- 1 | ## 利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites (作者:陳星銘) 2 | 3 | 在只有免費服務才使用 的這個世代,如果只是一個Demo的小型網站自然不想使用到雲端的SQL DB來做為DataBase (其實只是不想花一個月150左右的DB費用XD) 4 | 5 | 鑑於想要使用免費Azure Websites,但又想要連接資料庫的人要怎麼做呢? 6 | 7 | 只能每個月砸150台幣買DB了嗎!? 8 | 9 | 當然是 **NO!** 10 | 11 | 今天就來教大家利用SQL Compact Edition不花一毛錢使用擁有 DataBase 的 Azure Websites 吧! 12 | 13 | 以下看圖說故事開始: 14 | 15 | ### 第一步:打開你的VS安裝兩個Nuget套件 16 | 17 | 為你的專案加入兩個Nuget套件,分別是 18 | 19 | 1. EntityFrame.SqlServerCompact  20 | 2. Microsoft SQL Server Compact Edition 21 | 22 | ![](../img/azure1.jpg) 23 | 24 | ### 第二步:加入以下連線字串至Web.Config ` ` 區段中 25 | 26 | ``` 27 | 28 | ``` 29 | 30 | 其中 31 | Data Source=|DataDirectory|CompactDB.sdf 可得到相對路徑的 App_Data\CompactDB.sdf 32 | 33 | ![](../img/azure2.jpg) 34 | 35 | ### 第三步:在App_Data中右鍵加入→新增項目→Sql Server 資料庫 36 | 37 | 注意:這裡我將檔名改為.sdf檔,因為.sdf 很適合小型專案使用,不需要用到.mdf 38 | 39 | ![](../img/azure3.jpg) 40 | 41 | 若你用的和我一樣是MVC的CodeFirst則是改掉你的連線字串後,讓DB自己產生出來,但是這之後有一個很重要的步驟!真的很重要!我卡在這邊很久!操作如下: 42 | 43 | 產生DB後→點選右上角顯示所有檔案→找到你的CompactDB.sdf→右鍵加入至專案 44 | 45 | ![](../img/azure4.jpg) 46 | 47 | ### 第四步:到你的Azure建立WebSites 48 | 49 | 左下新增→接著如圖選擇建立網站 50 | 51 | ![](../img/azure5.jpg) 52 | 53 | ### 第五步: 54 | 55 | 建好網站後,點選你的網站,點選上方設定,拉到下面,填入剛剛的連接字串,選擇"自訂",按下方儲存 56 | 57 | ![](../img/azure6.jpg) 58 | 59 | ### 第六步: 60 | 61 | 到儀表板,點選下載發行設定檔,將其儲存在電腦中 62 | 63 | ![](../img/azure7.jpg) 64 | 65 | ### 第七步: 66 | 67 | 對你的專案按右鍵→發行→匯入→選到剛剛的設定檔→確定→發行 68 | 69 | ![](../img/azure8.jpg) 70 | 71 | 然後就發行成功囉!完成 [網址參考](http://websitewithdbforfree.azurewebsites.net/) 72 | 73 | 希望有幫助到大家 的錢包 !XD 74 | 75 | ### 授權說明: 76 | 77 | * 本著作係採用姓名標示-非商業性-相同方式分享 3.0 台灣授權。欲查看本授權條款副本,請到 ,或寫信至Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. 78 | 79 | -------------------------------------------------------------------------------- /htm/article5.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 | 21 |

Memory Sanitization (作者:研發養成所 Bridan)

22 |

什麼叫記憶體衛生處理?讓我們先看個故事再做說明。

23 |

阿誠是某高科技公司的工程師,他負責 使用儀器量測新產品實驗數據,有位同事阿堅和他很要好,常常去實驗室找他聊天,其實阿堅是另一家公司派來長期臥底的間諜,專門探詢公司最新研發的產品。公司有一台極輕巧的溫度監控儀,阿誠常使用它對新產品零件溫度監控,實驗完畢後,資料當然改存到電腦中,並且依據儀器說明書上,資料清除步驟清資料。一天阿堅向阿誠借用這儀器,其實他是把儀器拿給儀器駭客進行逆向工程,去解碼原始實驗資料。

24 |

從這故事,你學到了什麼?有許多科技公司對資訊安全非常在意,連清理資料也要徹底破壞!

25 |

大家都知道在 電腦上刪除檔案,只不過是把檔案搬移到資源回收筒,隨時可以檔案還原,稍微注意的人,還會清除資源回收筒的檔案,更高竿的會再進行衛生處理,徹底洗掉不要的資料。

26 |

一般資料庫,清除資料的做法是破壞資料索引,簡單的說,利用一個索引指示有多少資料在資料庫中,如果索引為N,表示有N筆資料在其中,使用者可以循序用指令將資料取出。當索引為零時,也表示資料庫資料清除。這方法雖然快速簡單,可是欠缺資料安全性,為避免上述事件發生,除了一般清除,還要另外設計徹底清除功能。換個例子說明,也就是上完廁所,除了擦屁股,沖水之外,不要忘記馬桶順便刷一刷洗一洗,徹底做個衛生處理。

27 |
28 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /source/info.md: -------------------------------------------------------------------------------- 1 | # 雜誌訊息 2 | 3 | ## 讀者訂閱 4 | 程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌,如果您願意成為本雜誌的專欄作家,請加入 [程式人雜誌社團] 一同共襄盛舉。 5 | 6 | 我們透過發行這本雜誌,希望讓大家可以讀到想讀的書,學到想學的技術,同時也讓寫作的朋友的作品能產生良好價值 – 那就是讓讀者根據雜誌的價值捐款給慈善團體。 7 | 讀雜誌做公益也不需要有壓力,您不需要每讀一本就急著去捐款,您可以讀了十本再捐,或者使用固定的月捐款方式,當成是雜誌訂閱費,或者是季捐款、一年捐一次等都 OK ! 甚至是單純當個讀者我們也都很歡迎! 8 | 9 | 本雜誌每期參考價:NT 50 元,如果您喜歡本雜誌,請將書款捐贈公益團體。例如可捐贈給「羅慧夫顱顏基金會 彰化銀行(009) 帳號:5234-01-41778-800」。(若匯款要加註可用「程式人雜誌」五個字) 10 | 11 | ## 投稿須知 12 | 13 | *給專欄寫作者:* 做公益不需要有壓力。如果您願意撰寫專欄,您可以輕鬆的寫,如果當月的稿件出不來,我們會安排其他稿件上場。 14 | 15 | *給網誌捐贈者:* 如果您沒時間寫專欄或投稿,沒關係,只要將您的網誌以 [創作共用的「姓名標示、非商業性、相同方式分享」授權] 並通知我們,我們會自動從中選取需要的文章進行編輯,放入適當的雜誌當中出刊。 16 | 17 | *給文章投稿者:* 程式人雜誌非常歡迎您加入作者的行列,如果您想撰寫任何文章或投稿,請用 markdown 或 LibreOffice 編輯好您的稿件,並於每個月 25 日前投稿到[程式人雜誌社團] 的檔案區,我們會盡可能將稿件編入隔月1號出版程式人雜誌當中,也歡迎您到社團中與我們一同討論。 18 | 19 | 如果您要投稿給程式人雜誌,我們最希望的格式是採用 markdown 的格式撰寫,然後將所有檔按壓縮為 zip 上傳到社團檔案區給我們, 如您想學習 markdown 的撰寫出版方式,可以參考 [看影片學 markdown 編輯出版流程] 一文。 20 | 21 | 如果您無法採用 markdown 的方式撰寫,也可以直接給我們您的稿件,像是 MS. Word 的 doc 檔或 LibreOffice 的 odt 檔都可以,我們 22 | 會將這些稿件改寫為 markdown 之後編入雜誌當中。 23 | 24 | ## 參與編輯 25 | 您也可以擔任程式人雜誌的編輯,甚至創造一個全新的公益雜誌,我們誠摯的邀請您加入「開放公益出版」的行列,如果您想擔任編輯或創造新雜誌,也歡迎到 [程式人雜誌社團] 來與我們討論相關事宜。 26 | 27 | ## 公益資訊 28 | 29 | ------------------------------------------------------------------------------------------------------------------------------------------------------------ 30 | 公益團體 聯絡資訊 服務對象 捐款帳號 31 | ------------------------------- ----------------------------- ----------------------------------------- ------------------------------------------- 32 | 財團法人羅慧夫顱顏基金會
顱顏患者 銀行:009彰化銀行民生分行
33 |
(如唇顎裂、小耳症或其他罕見顱顏缺陷) 帳號:5234-01-41778-800 34 | 02-27190408分機 232 35 | 36 | 社團法人台灣省兒童少年成長協會
單親、隔代教養.弱勢及一般家庭之兒童青少年 銀行:新光銀行
37 |
戶名:台灣省兒童少年成長協會
38 | 04-23058005 帳號:103-0912-10-000212-0 39 | ------------------------------- ----------------------------- ----------------------------------------- ------------------------------------------- 40 | 41 | [看影片學 markdown 編輯出版流程]:https://dl.dropboxusercontent.com/u/101584453/pmag/201304/htm/video1.html 42 | -------------------------------------------------------------------------------- /htm/focus1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

科學計算軟體簡介

22 |

很多人都曾經使用過「科學計算軟體」,特別是對於進行學術研究的人員而言,這些軟體可以說是不可或缺的。

23 |

在工程領域,最常被使用的科學計算軟體是 MatLab,這個軟體從「矩陣運算」出發,建構出了龐大的函式庫,讓使用者可以輕易的透過 Matlab 進行電腦實驗。

24 |

另外、在社會科學與統計學領域,很多人會用 SPSS、SAS 等軟體做統計分析,這兩個軟體是從統計出發的科學計算工具。

25 |

事實上、開放原始碼領域也有對應的科學計算軟體,像是 R 與 Octave 都是 Open Source 的科學計算軟體。

26 |
27 | 圖、Octave 軟體的官方網站

圖、Octave 軟體的官方網站

28 |
29 |

R 與 SPSS、SAS 的出發點較類似,是從機率統計領域開始建構的,而 Octave 則完全模仿 Matlab 的語法,試圖建構一個與 Matlab 語言相容的科學計算平台,讓 Matlab 的程式資源也可以被 Octave 社群所使用。

30 |
31 | 圖、R 軟體的官方網站

圖、R 軟體的官方網站

32 |
33 |

在開源的科學計算軟體中, R 軟體 的使用者似乎是最多的,但是由於 R 採用的程式語言 S3 並非 OpenSource 程式領域的主流,因此也有人試圖用 Python 等語言去建構出科學計算的環境,像是 SciPy 就整合了 numpy 、sympy、Matplotlib、

34 |
35 | 圖、SciPy 的官方網站

圖、SciPy 的官方網站

36 |
37 |

雖然已經有了這麼多開放原始碼的科學計算軟體,而且我本身也是 R 的使用者,但是、我仍然感到遺憾!

38 |

因為我沒辦法找到建構在 JavaScript 語言上的科學計算軟體,所以、我打算自己建造一個,這個計劃就稱為 JsLab (JavaScript Laboratory)。

39 |

在下列文章中,我將介紹自己為何要建構 JsLab 專案,如何建構 JsLab 專案,並與大家分享我在建構 JsLab 專案時所學到的一些經驗與心得。

40 |
41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /source/article1.md: -------------------------------------------------------------------------------- 1 | ## d3.js -- 互動式繪圖框架 2 | 3 | d3.js 是一個在瀏覽器裏使用的互動式繪圖框架,使用 HTML、CSS、JavaScript 與 SVG (Scalable Vector Graphics) 等技術。 4 | 5 | d3.js 專案起始於 2011 年,是從 [Protovis](http://en.wikipedia.org/wiki/Protovis) 專案修改過來的,通常我們會用 D3 來產生 SVG 或 CSS 的繪圖結果,在瀏覽器上檢視時還可以利用 SVG 或 CSS 與使用者進行互動。 6 | 7 | d3.js 的用法有點像 jQuery,都是透過選擇器來進行選取後操作的,舉例而言、下列指令可以選出所有 p 標記的節點並將顏色修改為 lavender (淡紫色、熏衣草)。 8 | 9 | ```javascript 10 | d3.selectAll("p") 11 | .style("color", "lavender"); 12 | ``` 13 | 14 | 我們可以透過「標記 tag、類別 class、代號 identifier、屬性 attribute、或位置 place 來選取節點,然後進行新增、刪除、修改等動作,然後透過設定 CSS 的轉移 (transition) 屬性,讓繪圖的結果可以和使用者進行互動,舉例而言、以下程式就會讓網頁裡的 p 標記節點逐漸地改變為紫色。 (d3.js 預設的改變速度為 250ms 完成轉換) 15 | 16 | ```javascript 17 | d3.selectAll("p") 18 | .transition() 19 | .style("color", "pink"); 20 | ``` 21 | 22 | 由於 SVG 裏的標記也是 HTML 的一部分, d3 的指令也可以選取 SVG 裏的內容,以下來自 [Mike Bostock] 網站的 [範例](http://bost.ocks.org/mike/circles/) 顯示了這個狀況: 23 | 24 | ```html 25 | 26 | 27 | 28 | 29 | 30 | ... 31 | 36 | ``` 37 | 38 | d3.js 的主要 API 包含下列幾類: 39 | 40 | * Selections 41 | * Transitions 42 | * Arrays 43 | * Math 44 | * Color 45 | * Scales 46 | * SVG 47 | * Time 48 | * Layouts 49 | * Geography 50 | * Geometry 51 | * Behaviors 52 | 53 | 而以下的專案則是延伸自 d3.js 的套件, 54 | 55 | * [freeDataMap](http://freedatamap.com/) - Company data visualisation tool 56 | * [dimple.js](http://dimplejs.org/) - Flexible axis-based charting API 57 | * [Cubism](http://square.github.io/cubism/) - Time series visualisation 58 | * [Rickshaw](http://code.shutterstock.com/rickshaw/) - Toolkit for creating interactive time series graphs 59 | * [NVD3](http://nvd3.org/) - Re-usable charts for d3 60 | * [Crossfilter](http://square.github.io/crossfilter/) - Fast Multidimensional Filtering for Coordinated Views 61 | * [dc.js](http://nickqizhu.github.io/dc.js/) - Dimensional Charting Javascript Library 62 | * [c3.js](http://c3js.org/) - D3-based reusable chart library 63 | 64 | 甚至還有人專門為 d3.js 寫了一本書,而且這本書還有中文版。 65 | 66 | * [網頁互動式資料視覺化:使用D3](http://www.books.com.tw/products/0010621239), Scott Murray. 67 | 68 | ### 參考文獻 69 | * Wikipedia: D3.js -- 70 | * Mike Bostock -- 71 | * 72 | * [D3 Gallery](https://github.com/mbostock/d3/wiki/Gallery) 73 | 74 | [Mike Bostock]:http://bost.ocks.org/mike/ 75 | 76 | -------------------------------------------------------------------------------- /htm/discuss1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 9 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 20 |
21 |

討論:本月討論精選

22 | 39 |

參考文獻

40 |
41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /source/article7.md: -------------------------------------------------------------------------------- 1 | ## 函數指標陣列 (Array of Function Pointers) (作者:研發養成所 Bridan) 2 | 3 | 函數指標陣列,這是一種 C/C++ 程式語言的高階設計技巧,希望能有較高的執行效能。 4 | 我以 Arduino 當作測試平台,比較兩種程式設計技巧,發現與我的認知有些差異。 5 | 6 | 先看傳統設計方式,用 switch case 執行不同功能: 7 | 8 | ```CPP 9 | // 10 | // Author: Bridan 11 | // http://4rdp.blogspot.com 12 | // Date: 2014/09/27 13 | // 14 | // Brief: Test switch case 15 | // 16 | 17 | void setup() { 18 | Serial.begin(9600); 19 | while (!Serial) { 20 | ; // wait for serial port to connect. Needed for Leonardo only 21 | } 22 | 23 | TCCR1A = 0x00; // Normal mode, just as a Timer 24 | TCCR1B &= ~_BV(CS12); // no prescaling 25 | TCCR1B &= ~_BV(CS11); 26 | TCCR1B |= _BV(CS10); 27 | } 28 | 29 | void loop() { 30 | byte i; 31 | 32 | TCNT1 = 0; // reset timer 33 | for (i=0 ; i<3 ; i++) { 34 | switch (i) { 35 | case 0: 36 | Serial.println("CASE 0"); 37 | break; 38 | case 1: 39 | Serial.println("CASE 1"); 40 | break; 41 | case 2: 42 | Serial.println("CASE 2"); 43 | break; 44 | } 45 | } 46 | Serial.println(TCNT1); 47 | } 48 | ``` 49 | 50 | switch case 3 個時,編譯 2410 bytes,執行 6092 ~ 6100 timer clock 51 | switch case 4 個時,編譯 2430 bytes,執行 8136 ~ 8146 timer clock 52 | switch case 5 個時,編譯 2458 bytes,執行 10185 ~ 10195 timer clock 53 | 54 | 將上面程式修改成函數指標陣列,以查表方式直接跳到執行的程式: 55 | 56 | ```CPP 57 | // 58 | // Author: Bridan 59 | // http://4rdp.blogspot.com 60 | // Date: 2014/09/27 61 | // 62 | // Brief: Test Array of Function Pointers 63 | // 64 | 65 | void setup() { 66 | Serial.begin(9600); 67 | while (!Serial) { 68 | ; // wait for serial port to connect. Needed for Leonardo only 69 | } 70 | 71 | TCCR1A = 0x00; // Normal mode, just as a Timer 72 | TCCR1B &= ~_BV(CS12); // no prescaling 73 | TCCR1B &= ~_BV(CS11); 74 | TCCR1B |= _BV(CS10); 75 | } 76 | 77 | void FUNC0(void) { 78 | Serial.println("CASE 0"); 79 | } 80 | void FUNC1(void) { 81 | Serial.println("CASE 1"); 82 | } 83 | void FUNC2(void) { 84 | Serial.println("CASE 2"); 85 | } 86 | 87 | void (*TABLE_JUMP[])(void) = { 88 | FUNC0, 89 | FUNC1, 90 | FUNC2 91 | }; 92 | 93 | void loop() { 94 | byte i; 95 | 96 | TCNT1 = 0; // reset timer 97 | for (i=0 ; i<3 ; i++) { 98 | (*TABLE_JUMP[i])(); 99 | } 100 | Serial.println(TCNT1); 101 | } 102 | ``` 103 | 104 | TABLE 3 個時,編譯 2438 bytes,執行 6082 ~ 6096 timer clock 105 | TABLE 4 個時,編譯 2470 bytes,執行 8130 ~ 8142 timer clock 106 | TABLE 5 個時,編譯 2504 bytes,執行 10176 ~ 10194 timer clock 107 | 108 | 以往我所用過的 compiler,switch case 相當於很多 if ... else ... 的組合,條件一個一個比較,數值越大的條件,花費比較的時間越多,以上面的例子在比較方面所費的時間 = 1 + 2 + 3 + ... + N,而函數指標陣列查表時間約 = 1 x N,比 switch case 有效率,這部分與結果相符 (比較條件太少,不易看出差異)。 109 | 110 | 至於程式碼大小,發現越多條件狀況,以函數指標陣列方式設計比 switch case 程式碼多?因為不清楚 Arduino compiler 如何設計,無法進一步評論,但直覺 Arduino compiler 缺少這方面最佳化處理。 111 | 112 | -------------------------------------------------------------------------------- /htm/home.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |

關於程式人雜誌

17 |

程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌。

18 |

雜誌下載

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
出刊年月epubipad:PDFA4:PDF單頁 HTM全部下載
2014年11月epubipad.pdfA4.pdfpmag.htmlgithub
41 |

本期內容

42 | 67 |

雜誌取得

68 |

程式人雜誌預定於每個月 1 日出刊,您可以從下列網址取得程式人雜誌的所有內容 (包含當月最新出刊的雜誌)。

69 | 72 |

連絡我們

73 |

竭誠歡迎程式人投稿,或者成為本雜誌的專欄作家,現在就可以加入 程式人雜誌社團 一同共襄盛舉。

74 |

本雜誌編輯為「陳鍾誠 (@ccckmit)」,若要聯絡編輯,請寄信到

80 |
81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /htm/article6.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 | 21 |

利用 SQL Compact Edition 免費建立擁有 DataBase 的 Azure Websites (作者:陳星銘)

22 |

在只有免費服務才使用 的這個世代,如果只是一個Demo的小型網站自然不想使用到雲端的SQL DB來做為DataBase (其實只是不想花一個月150左右的DB費用XD)

23 |

鑑於想要使用免費Azure Websites,但又想要連接資料庫的人要怎麼做呢?

24 |

只能每個月砸150台幣買DB了嗎!?

25 |

當然是 NO!

26 |

今天就來教大家利用SQL Compact Edition不花一毛錢使用擁有 DataBase 的 Azure Websites 吧!

27 |

以下看圖說故事開始:

28 |

第一步:打開你的VS安裝兩個Nuget套件

29 |

為你的專案加入兩個Nuget套件,分別是

30 |
    31 |
  1. EntityFrame.SqlServerCompact 
  2. 32 |
  3. Microsoft SQL Server Compact Edition
  4. 33 |
34 |
35 | 36 |
37 |

 第二步:加入以下連線字串至Web.Config <connectionStrings> </connectionStrings> 區段中

38 |
<add name ="DefaultConnection" connectionString ="Data Source=|DataDirectory|CompactDB.sdf" providerName ="System.Data.SqlServerCe.4.0" />
39 |

其中 Data Source=|DataDirectory|CompactDB.sdf 可得到相對路徑的 App_Data.sdf

40 |
41 | 42 |
43 |

第三步:在App_Data中右鍵加入→新增項目→Sql Server 資料庫

44 |

注意:這裡我將檔名改為.sdf檔,因為.sdf 很適合小型專案使用,不需要用到.mdf

45 |
46 | 47 |
48 |

若你用的和我一樣是MVC的CodeFirst則是改掉你的連線字串後,讓DB自己產生出來,但是這之後有一個很重要的步驟!真的很重要!我卡在這邊很久!操作如下:

49 |

產生DB後→點選右上角顯示所有檔案→找到你的CompactDB.sdf→右鍵加入至專案

50 |
51 | 52 |
53 |

第四步:到你的Azure建立WebSites

54 |

左下新增→接著如圖選擇建立網站

55 |
56 | 57 |
58 |

第五步:

59 |

建好網站後,點選你的網站,點選上方設定,拉到下面,填入剛剛的連接字串,選擇"自訂",按下方儲存

60 |
61 | 62 |
63 |

第六步:

64 |

到儀表板,點選下載發行設定檔,將其儲存在電腦中

65 |
66 | 67 |
68 |

第七步:

69 |

對你的專案按右鍵→發行→匯入→選到剛剛的設定檔→確定→發行

70 |
71 | 72 |
73 |

然後就發行成功囉!完成 網址參考

74 |

希望有幫助到大家 的錢包 !XD

75 |

授權說明:

76 |
    77 |
  • 本著作係採用姓名標示-非商業性-相同方式分享 3.0 台灣授權。欲查看本授權條款副本,請到 http://creativecommons.org/licenses/by-nc-sa/3.0/tw/ ,或寫信至Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA.
  • 78 |
79 |
80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /htm/info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

14 |
15 |
16 |
17 | 25 |
26 |

雜誌訊息

27 |

讀者訂閱

28 |

程式人雜誌是一個結合「開放原始碼與公益捐款活動」的雜誌,簡稱「開放公益雜誌」。開放公益雜誌本著「讀書做善事、寫書做公益」的精神,我們非常歡迎程式人認養專欄、或者捐出您的網誌,如果您願意成為本雜誌的專欄作家,請加入 程式人雜誌社團 一同共襄盛舉。

29 |

我們透過發行這本雜誌,希望讓大家可以讀到想讀的書,學到想學的技術,同時也讓寫作的朋友的作品能產生良好價值 – 那就是讓讀者根據雜誌的價值捐款給慈善團體。 讀雜誌做公益也不需要有壓力,您不需要每讀一本就急著去捐款,您可以讀了十本再捐,或者使用固定的月捐款方式,當成是雜誌訂閱費,或者是季捐款、一年捐一次等都 OK ! 甚至是單純當個讀者我們也都很歡迎!

30 |

本雜誌每期參考價:NT 50 元,如果您喜歡本雜誌,請將書款捐贈公益團體。例如可捐贈給「羅慧夫顱顏基金會 彰化銀行(009) 帳號:5234-01-41778-800」。(若匯款要加註可用「程式人雜誌」五個字)

31 |

投稿須知

32 |

給專欄寫作者: 做公益不需要有壓力。如果您願意撰寫專欄,您可以輕鬆的寫,如果當月的稿件出不來,我們會安排其他稿件上場。

33 |

給網誌捐贈者: 如果您沒時間寫專欄或投稿,沒關係,只要將您的網誌以 [創作共用的「姓名標示、非商業性、相同方式分享」授權] 並通知我們,我們會自動從中選取需要的文章進行編輯,放入適當的雜誌當中出刊。

34 |

給文章投稿者: 程式人雜誌非常歡迎您加入作者的行列,如果您想撰寫任何文章或投稿,請用 markdown 或 LibreOffice 編輯好您的稿件,並於每個月 25 日前投稿到程式人雜誌社團 的檔案區,我們會盡可能將稿件編入隔月1號出版程式人雜誌當中,也歡迎您到社團中與我們一同討論。

35 |

如果您要投稿給程式人雜誌,我們最希望的格式是採用 markdown 的格式撰寫,然後將所有檔按壓縮為 zip 上傳到社團檔案區給我們, 如您想學習 markdown 的撰寫出版方式,可以參考 看影片學 markdown 編輯出版流程 一文。

36 |

如果您無法採用 markdown 的方式撰寫,也可以直接給我們您的稿件,像是 MS. Word 的 doc 檔或 LibreOffice 的 odt 檔都可以,我們 會將這些稿件改寫為 markdown 之後編入雜誌當中。

37 |

參與編輯

38 |

您也可以擔任程式人雜誌的編輯,甚至創造一個全新的公益雜誌,我們誠摯的邀請您加入「開放公益出版」的行列,如果您想擔任編輯或創造新雜誌,也歡迎到 程式人雜誌社團 來與我們討論相關事宜。

39 |

公益資訊

40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 74 | 75 | 76 | 77 |
公益團體聯絡資訊服務對象捐款帳號
財團法人羅慧夫顱顏基金會http://www.nncf.org/

02-27190408分機 232
顱顏患者 (如唇顎裂、小耳症或其他罕見顱顏缺陷)銀行:009彰化銀行民生分行
帳號:5234-01-41778-800
社團法人台灣省兒童少年成長協會http://www.cyga.org/

04-23058005
單親、隔代教養.弱勢及一般家庭之兒童青少年銀行:新光銀行
戶名:台灣省兒童少年成長協會
帳號:103-0912-10-000212-0
78 |
79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /htm/article2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

c3.js -- 基於 d3.js 的簡易繪圖框架

41 |

雖然 d3.js 很強大,但是卻並不容易使用,如果我們只是要畫一些簡易的圖形,可以採用延伸自 d3.js 的 c3.js 。

42 |

C3.js 的使用非常的簡單,而且互動性很強大。舉例而言,以下是 C3.js 的一個範例,您將滑鼠游標移到圖形上,會顯示對應軸線的資料表格,這讓使用者可以很清楚的看到圖形所對應的數據,這是非常具有互動性的顯示方式。

43 |
44 | 圖、C3.js 的一個繪圖範例

圖、C3.js 的一個繪圖範例

45 |
46 |

您可以點選下列網址試試看這個範例,應該可以感覺到 C3.js 好用的地方。

47 | 50 |

而且、要產生上述的圖形,也只需要短短幾行簡單的資料與程式,其程式碼如下所示:

51 |
var chart = c3.generate({
52 |     data: {
53 |         columns: [
54 |             ['data1', 30, 20, 50, 40, 60, 50],
55 |             ['data2', 200, 130, 90, 240, 130, 220],
56 |             ['data3', 300, 200, 160, 400, 250, 250],
57 |             ['data4', 200, 130, 90, 240, 130, 220],
58 |             ['data5', 130, 120, 150, 140, 160, 150],
59 |             ['data6', 90, 70, 20, 50, 60, 120],
60 |         ],
61 |         type: 'bar',
62 |         types: {
63 |             data3: 'spline',
64 |             data4: 'line',
65 |             data6: 'area',
66 |         },
67 |         groups: [
68 |             ['data1','data2']
69 |         ]
70 |     }
71 | });
72 |

從以上的範例中,您應該可以看到 C3 這個架構的優點,相較於 D3 而言, C3 容易使用多了。

73 |

但是、 C3 並沒有辦法完全發揮 D3 的功能,像是筆者就沒看到 C3 具有任何可以繪製統計 box chart 的功能,因此對於某些較少見的情況而言,我們還是得直接採用 D3 ,另外 C3 的文件說明並不完整,這是筆者所看到的 C3 框架之缺陷。

74 |

參考文獻

75 | 78 |
79 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /source/article4.md: -------------------------------------------------------------------------------- 1 | ## CodeMirror -- 有 IntelliSense 功能的網頁版開源編輯器 2 | 3 | 在建構 jsLab 科學計算平台的過程中,由於要讓使用者在 JavaScript 程式編輯上有更好的感受,而不是只能依賴死板板的 textarea 區塊,所以我們找了幾個用 javascript 建構的網頁版程式碼編輯器,像是 Ace、Atom、EditArea 與 CodeMirror 等專案,最後我們認為 CodeMirror 最適合我們使用,因為 CodeMirror 的資源完整,而且具有支援 JavaScript 語言 IntelliSense 功能的插件。 4 | 5 | * 6 | * 7 | * 8 | * 9 | 10 | CodeMirror 支援超過六十種語言的上色與編輯功能,包含 HTML、XML、Javascript、Python、Ruby、C/C++/C#、.... 等等,您可以參考下列網頁。 11 | 12 | * 13 | 14 | 另外、 CodeMirror 還支援了下列的特色功能。 15 | 16 | * A powerful, composable language mode system 17 | * Autocompletion (XML) 18 | * Code folding 19 | * Configurable keybindings 20 | * Vim, Emacs, and Sublime Text bindings 21 | * Search and replace interface 22 | * Bracket and tag matching 23 | * Support for split views 24 | * Linter integration 25 | * Mixing font sizes and styles 26 | * Various themes 27 | * Able to resize to fit content 28 | * Inline and block widgets 29 | * Programmable gutters 30 | * Making ranges of text styled, read-only, or atomic 31 | * Bi-directional text support 32 | * Many other methods and addons... 33 | 34 | 其中我們最需要的是 JavaScript 的 Intellisense 功能,該功能的範例網址如下: 35 | 36 | * 37 | 38 | 可惜的是,該範例使用 Ctrl-Space 做為 Intellisense 的功能鍵,但是這個按鍵與繁體中文 windows 的輸入法切換功能相衝,所以沒辦法正常運作,因此我們將該範例的 「Ctrl-Space」 改為 「Ctrl-.」 ,以避免這種衝突的情況,修改版的範例的網址與程式碼如下。 39 | 40 | * 41 | 42 | ```javascript 43 | 44 | 45 | CodeMirror: Autocomplete Demo 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 68 | 69 |
70 |

Autocomplete Demo

71 |
108 | 109 |

Press ctrl-. to activate autocompletion. Built 110 | on top of the show-hint 111 | and javascript-hint 112 | addons.

113 | 114 | 121 |
122 | ``` 123 | 124 | 不過、雖然 CodeMirror 支援了 JavaScript 的 Intellisense 功能,但是卻不徹底,對於像是字串之類的語法,他可以顯示提示函數與訊息,但對於變數的部分,卻無法正確提示,以下是一個可以正確提示的範例。 125 | 126 | ![圖、CodeMirror 可以正確提示的 JavaScript 編輯範例](../img/CodeMirrorJsComplete.jpg) 127 | 128 | 如果需要更進一步的正確提示功能,恐怕還是得修改 CodeMirror 的 `../addon/hint/javascript-hint.js` 模組才行。 129 | 130 | 雖然 CodeMirror 已經算不錯了,不過我想還有進步空間,但大體來說 CodeMirror 已經是很好的網頁程式編輯器了。 131 | 132 | 不過、如果您需要的是可以加上「粗體、斜體、字型、超連結、....」等功能,那就不是 CodeMirror 所具備的功能了,這種功能是 RichText Editor 才具備的,您可以參考下列文章中的 RichText 編輯器。 133 | 134 | * [5 Free JavaScript Libraries to Add Text Editing to Your Web Application](http://blog.smartbear.com/programming/five-free-javascript-libraries-to-add-text-editing-to-your-web-application/) 135 | 136 | 137 | ### 參考文獻 138 | * 139 | * 140 | 141 | -------------------------------------------------------------------------------- /source/focus3.md: -------------------------------------------------------------------------------- 1 | ## 「JsLab 科學計算平台」背後的開放原始碼結構 2 | 3 | 為了要用 JavaScript 建構出科學計算平台,我們創建了以下的 JsLab 開放原始碼專案。 4 | 5 | * 6 | 7 | 我們大量的採用了 JavaScript 的開放原始碼函式庫,像是在「機率統計」領域採用了 jStat 這個專案,在繪圖領域採用了 d3.js、c3.js、vis.js 等等,這些專案的網址如下。 8 | 9 | * 10 | * 11 | * 12 | * 13 | 14 | JsLab 科學計算平台的核心,是一組基於 jStat 專案的重新封裝,我們將 jStat 重新封裝成類似 R 函式庫的介面,並且加上了一些 jStat 當中所沒有的功能,特別是統計檢定的部份,形成了 [R.js] 這個 JavaScript 程式,讓 JavaScript 也能擁有類似 R 軟體的機率統計函式庫。 15 | 16 | 我們雖然使用了 d3.js 這個繪圖函式庫進行 2D 繪圖,但由於 d3.js 並不容易使用,所以我們採用了 c3.js 這個基於 d3 的延伸套件,簡化 d3 繪圖函式庫的使用,讓我們不需瞭解太多繪圖的細節就能寫出 JsLab 的繪圖函式庫。 17 | 18 | 舉例而言、下列的圖形就是依靠 c3.js 所繪製的,只不過我們將 c3.js 進一步封裝到 JsLab 的 [G.js] 這個的繪圖函式庫當中而已。 19 | 20 | ![](../img/jsLabC3Graph.jpg) 21 | 22 | 以下是我們將 c3.js 重新封裝成 [G.js] 的程式碼片段。 23 | 24 | 檔案: [G.js] 25 | 26 | ```javascript 27 | var C3G=function() { 28 | this.g = { 29 | data: { 30 | xs: {}, 31 | columns: [ /*["x", 1, 2, 3, 4 ]*/ ], 32 | type: "line", 33 | types : {} 34 | }, 35 | axis: { 36 | x: { 37 | label: 'X', 38 | tick: { fit: false, format:d3.format(".2f") } 39 | }, 40 | y: { label: 'Y', 41 | tick : { format: d3.format(".2f") } 42 | } 43 | }, 44 | bar: { width: { ratio: 0.9 } }, 45 | }; 46 | this.varcount = 0; 47 | this.xrange(-10, 10); 48 | this.step = 1; 49 | this.setrange = false; 50 | } 51 | .... 52 | C3G.prototype.hist = function(x, options) { 53 | var name = R.opt(options, "name", this.tempvar()); 54 | var mode = R.opt(options, "mode", ""); 55 | var step = R.opt(options, "step", this.step); 56 | var from = R.opt(options, "from", this.xmin); 57 | var to = R.opt(options, "to", this.xmax); 58 | this.g.data.types[name] = "bar"; 59 | this.g.data.xs[name] = name+"x"; 60 | var xc = R.steps(from+step/2.0, to, step); 61 | var n = (to-from)/step + 1; 62 | var count = R.repeats(0, n); 63 | for (var i in x) { 64 | var slot=Math.floor((x[i]-from)/step); 65 | if (slot>=0 && slot < n) 66 | count[slot]++; 67 | } 68 | this.g.data.columns.push([name+"x"].concat(xc)); 69 | var total = R.sum(count); 70 | if (mode === "normalized") 71 | count = R.apply(count, function(c) { return (1.0/step)*(c/total); }); 72 | this.g.data.columns.push([name].concat(count)); 73 | } 74 | ... 75 | C3G.prototype.show = function() { 76 | if (typeof(module)==="undefined") 77 | return c3.generate(this.g); 78 | } 79 | ``` 80 | 81 | 另外、由於 d3.js 並沒有支援 3D 曲面圖形的繪製,所以我們又引入了 vis.js 這個繪圖函式庫來完成 3D 圖形的繪製工作。 82 | 83 | 以下是我們將 vis.js 封裝成 G.js 的程式碼片段 84 | 85 | 檔案: [G.js] 86 | 87 | ```javascript 88 | ... 89 | VISG.prototype.curve3d = function(f, box) { 90 | // Create and populate a data table. 91 | var data = new vis.DataSet(); 92 | // create some nice looking data with sin/cos 93 | var counter = 0; 94 | var steps = 50; // number of datapoints will be steps*steps 95 | var axisMax = 314; 96 | var axisStep = axisMax / steps; 97 | for (var x = 0; x < axisMax; x+=axisStep) { 98 | for (var y = 0; y < axisMax; y+=axisStep) { 99 | var value = f(x,y); 100 | data.add({id:counter++,x:x,y:y,z:value,style:value}); 101 | } 102 | } 103 | this.graph = new vis.Graph3d(box, data, this.options); 104 | } 105 | ... 106 | G.curve3d = function(f) { 107 | G.visg.curve3d(f, G.box); 108 | } 109 | ``` 110 | 111 | 接著、為了讓使用者編輯程式可以更容易,我們採用了這個 JavaScript 開源線上編輯器專案,該專案之援類似微軟 Visual Studio 的 IntelliSense 這樣的函數提示功能, 112 | 113 | * 114 | 115 | ![圖、JsLab 當中的程式碼上色與 IntelliSense 功能](../img/JsLabIntelliSense.jpg) 116 | 117 | 以下是我們將 codemirror 封裝成 [E.js] (Editor) 的完整程式碼。 118 | 119 | 檔案: [E.js] 120 | 121 | ```javascript 122 | "use strict"; 123 | 124 | U.use("../js/codemirror/lib/codemirror.js", "CodeMirror"); 125 | U.use("../js/codemirror/addon/hint/show-hint.js"); 126 | U.use("../js/codemirror/addon/hint/javascript-hint.js"); 127 | U.use("../js/codemirror/mode/javascript/javascript.js"); 128 | 129 | E = {}; 130 | 131 | if (typeof module!=="undefined") module.exports = E; 132 | 133 | E.editor = null; 134 | 135 | E.loadEditor = function(codebox) { 136 | E.codebox = codebox; 137 | E.editor = CodeMirror.fromTextArea(codebox, { 138 | lineNumbers: true, 139 | extraKeys: {"Ctrl-.": "autocomplete"}, 140 | lineWrapping: true, 141 | styleActiveLine: true, 142 | mode: {name: "javascript", globalVars: true} 143 | }); 144 | 145 | E.editor.on('update', function(instance){ 146 | E.codebox.value = instance.getValue(); 147 | }); 148 | } 149 | ``` 150 | 151 | 未來、我們可能會進一步整合更多的函式庫,目前預計在「矩陣運算領域」會採用了 jStat 與 numeric.js 等函式庫,而在數位訊號語音處理領域可能會採用 DSP.js,影像處理領域可能採用 CamanJS 152 | 等等,這些函式庫的網址如下: 153 | 154 | * 155 | * 156 | * 157 | 158 | 目前、網路上的 JavaScript 的函式庫還持續的急速增長中,我們相信之後會有更多更好用的 JavaScript 科學計算函式庫出現,我們只要能將這些好用的函式庫整合進來,就能創建一個完整的科學計算平台了,而這也正是 JsLab 計劃所想要達成的目標。 159 | 160 | 由於 JavaScript 是瀏覽器當中唯一能使用的官方語言,因此我們認為未來 JavaScript 的發揮空間將會越來越大,就像 Jeff Atwood 在 2007 年所提出的 Atwood's Law 所說的: 161 | 162 | > Any application that can be written in JavaScript, will eventually be written in JavaScript. 163 | 164 | 換句話說 -- 「任何可以寫成 JavaScript 的應用程式,最後都會被寫成 JavaScript」。 165 | 166 | 如果 Atwood's Law 成立的話,那基於 JavaScript 的科學計算平台就應該要出現啊! 167 | 168 | 我們正在以行動來實現 Atwood 的話,這個行動的代號就是 JsLab 。 169 | 170 | ### 參考文獻 171 | 172 | * [Atwood定律:“任何可以使用JavaScript来编写的应用,最终会由JavaScript编写。”](http://www.iterduo.com/0401-atwood.html) 173 | 174 | [G.js]:https://github.com/ccckmit/jslab/blob/gh-pages/source/G.js 175 | [E.js]:https://github.com/ccckmit/jslab/blob/gh-pages/source/E.js 176 | [R.js]:https://github.com/ccckmit/jslab/blob/gh-pages/source/R.js 177 | 178 | -------------------------------------------------------------------------------- /source/article3.md: -------------------------------------------------------------------------------- 1 | ## Vis.js -- 另一個強大的 JavaScript 繪圖函式庫 2 | 3 | 雖然前述的 d3.js 與 c3.js 可以做到繪圖功能,但是這兩個函式庫強調的是互動性介面,而不是繪圖功能的部份。 4 | 5 | 於是、我找到了 vis.js 這個專注於繪圖的函式庫,這個函式庫雖然再互動性上表現得沒有 c3 那麼好,但是在繪圖功能上卻非常的完整,該有的圖型幾乎都有,特別是有關「 3D 地形圖」、「網路線圖」和的部份,是 C3 所不具備的功能,因此我們拿 vis.js 來繪製這兩類的圖形。 6 | 7 | 您可以點選下列連結,看看 vis.js 的眾多範例,相信您會對這個繪圖框架感到印象深刻的。 8 | 9 | * 10 | 11 | 舉例而言、以下網頁是用來繪製 3D 地形圖的完整原始碼, 12 | 13 | 網址: 14 | 15 | ![圖、用 Vis.js 繪製 3D 圖形](../img/vis3D.jpg) 16 | 17 | 以下是上述範例的完整 HTML 檔案。 18 | 19 | ```javascript 20 | 21 | 22 | 23 | Graph 3D demo 24 | 25 | 28 | 29 | 30 | 31 | 72 | 73 | 74 | 75 |
76 | 77 |
78 | 79 | 80 | ``` 81 | 82 | 而在網路圖方面,您甚至可以指定每個節點應該呈現的圖片,以下是一個繪製電腦網路圖的範例。 83 | 84 | * 85 | 86 | ![圖、用 vis.js 繪製電腦網路圖](../img/visNet.jpg) 87 | 88 | 以下是上述範例的完整 HTML 檔案。 89 | 90 | ```javascript 91 | 92 | 93 | 94 | Network | Images 95 | 96 | 106 | 107 | 108 | 109 | 110 | 167 | 168 | 169 | 170 | 171 |
172 | 173 | 174 | 175 | ``` 176 | 177 | 透過這兩個範例,相信您應該可以感覺到 vis.js 的誠意,這真的是一個相當棒的繪圖函式庫啊! 178 | 179 | ### 參考文獻 180 | * 181 | 182 | -------------------------------------------------------------------------------- /css/pmag.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, iframe, 2 | p, blockquote, pre, 3 | a, abbr, acronym, address, big, cite, code, 4 | del, dfn, em, img, ins, kbd, q, s, samp, 5 | small, strike, strong, sub, sup, tt, var, 6 | b, u, i, center, 7 | dl, dt, dd, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td, 10 | article, aside, canvas, details, embed, 11 | figure, figcaption, footer, header, hgroup, 12 | menu, nav, output, ruby, section, summary, 13 | time, mark, audio, video { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font: inherit; 18 | vertical-align: baseline; 19 | line-height:160%; 20 | } 21 | 22 | #cover-image { 23 | width:100%; 24 | } 25 | 26 | div>ol.toc { 27 | list-style-type:disc; 28 | } 29 | 30 | ol.toc { 31 | list-style-type:circle; 32 | } 33 | 34 | blockquote { 35 | margin: 10px; 36 | padding-left: 10px; 37 | padding-right: 10px; 38 | padding-top: 1px; 39 | padding-bottom: 1px; 40 | border: 3px double #373737; 41 | color:#333333; 42 | } 43 | 44 | h1, h1 a { font-size: xx-large; color:#050505; text-align:center; margin:30px; font-weight: bold; font-family: 'DFKai-sb', 'Tahoma'; } 45 | 46 | h2, h2 a { font-size: x-large; color:#8B008B; margin-top:30px; margin-bottom:30px; font-weight: bold; font-family: 'DFKai-sb', 'Tahoma'; } 47 | 48 | h3, h3 a { font-size: large; color:#000080; font-weight: bold; font-family: 'DFKai-sb', 'Tahoma'; } 49 | 50 | h4, h4 a { font-size: medium; color:#4B0082; font-weight: bold; font-family: 'DFKai-sb', 'Tahoma'; } 51 | 52 | h5, h5 a { font-size: small ; color:#708090; font-weight: bold; font-family: 'DFKai-sb', 'Tahoma'; } 53 | 54 | h6, h6 a { font-size: x-small; color:#000080; } 55 | 56 | p { 57 | font-family: 'Pmingliu', 'Tahoma'; 58 | margin: 10px 0 15px 0; 59 | font-size:100%; 60 | color:#353535; 61 | } 62 | 63 | li { 64 | font-size:100%; 65 | } 66 | 67 | footer p { 68 | color: #f2f2f2; 69 | } 70 | 71 | a { 72 | text-decoration: none; 73 | color: #007edf; 74 | text-shadow: none; 75 | 76 | transition: color 0.5s ease; 77 | transition: text-shadow 0.5s ease; 78 | -webkit-transition: color 0.5s ease; 79 | -webkit-transition: text-shadow 0.5s ease; 80 | -moz-transition: color 0.5s ease; 81 | -moz-transition: text-shadow 0.5s ease; 82 | -o-transition: color 0.5s ease; 83 | -o-transition: text-shadow 0.5s ease; 84 | -ms-transition: color 0.5s ease; 85 | -ms-transition: text-shadow 0.5s ease; 86 | } 87 | 88 | table { 89 | border-collapse: collapse; 90 | border-spacing: 0; 91 | border: 1px solid #373737; 92 | margin-bottom: 20px; 93 | text-align: left; 94 | margin-left:auto; 95 | margin-right:auto; 96 | } 97 | 98 | th { 99 | padding: 10px; 100 | background-color:black; 101 | color:white; 102 | } 103 | 104 | td { 105 | padding: 10px; 106 | vertical-align: middle; 107 | border: 1px solid #373737; 108 | } 109 | 110 | em { 111 | color: blue; 112 | } 113 | 114 | strong { 115 | font-weight:bold; 116 | color: red; 117 | } 118 | 119 | 120 | #header_wrap { 121 | margin: 0; 122 | padding: 16px; 123 | border: 0; 124 | font: inherit; 125 | vertical-align: baseline; 126 | background-color:black; 127 | color:white; 128 | } 129 | 130 | #header_wrap h1, #header_wrap h1 sub, #header_wrap h1 a { 131 | color:white; 132 | font-family: 'DFKai-sb', 'Tahoma'; 133 | } 134 | 135 | #header_wrap sub { 136 | color:white; 137 | font-size:60%; 138 | } 139 | 140 | #bar, #bar a, #header_wrap a, #header_wrap h1 sub a { 141 | color:white; 142 | width:95%; 143 | text-align:right; 144 | font-weight:bold; 145 | } 146 | 147 | .title, .author, .date { 148 | color:#333333; 149 | text-align:center; 150 | font-family: 'DFKai-sb', 'Tahoma' ; 151 | } 152 | 153 | .title { font-size:xx-large; line-height:800%; } 154 | 155 | .author { font-size:large; line-height:300%; } 156 | 157 | .date { font-size:large; line-height:300%; } 158 | 159 | 160 | #content { 161 | margin:10px; 162 | padding:10px; 163 | } 164 | 165 | pre { 166 | border: 1px solid #373737; 167 | background-color:#efefef; 168 | color:#3f3f3f; 169 | font-size:medium; 170 | width:95%; 171 | padding:10px; 172 | /* wrap ,自動換行 */ 173 | white-space: pre-wrap; /* css-3 */ 174 | white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ 175 | white-space: -pre-wrap; /* Opera 4-6 */ 176 | white-space: -o-pre-wrap; /* Opera 7 */ 177 | word-wrap: break-word; /* Internet Explorer 5.5+ */ 178 | } 179 | 180 | code { 181 | // font-family: SimSun; 182 | // color:blue; 183 | font-size:100%; 184 | } 185 | 186 | pre code { 187 | font-family: SimSun; 188 | font-size:125%; 189 | } 190 | 191 | .figure { 192 | margin:10px; 193 | padding:10px; 194 | margin-left: auto; 195 | margin-right: auto; 196 | display: block; 197 | } 198 | 199 | img { vertical-align:middle; } 200 | 201 | .figure img { 202 | margin-left: auto; 203 | margin-right: auto; 204 | display: block; 205 | } 206 | 207 | .figure .caption { 208 | text-align:center; 209 | } 210 | 211 | #TOC { 212 | } 213 | 214 | #footer { 215 | text-align:center; 216 | font-size:small; 217 | color:#6f6f6f; 218 | margin: 10px; 219 | padding: 10px; 220 | } 221 | 222 | /* JavaScript Style */ 223 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { 224 | margin: 0; padding: 0; vertical-align: baseline; border: none; } 225 | table.sourceCode { width: 100%; } 226 | td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #afafaf; border-right: 1px solid #aaaaaa; } 227 | td.sourceCode { padding-left: 5px; } 228 | code > span.kw { color: #007020; font-weight: bold; } 229 | code > span.dt { color: #902000; } 230 | code > span.dv { color: #40a070; } 231 | code > span.bn { color: #40a070; } 232 | code > span.fl { color: #40a070; } 233 | code > span.ch { color: #4070a0; } 234 | code > span.st { color: #4070a0; } 235 | code > span.co { color: #60a0b0; font-style: italic; } 236 | code > span.ot { color: #007020; } 237 | code > span.al { color: #ff0000; font-weight: bold; } 238 | code > span.fu { color: #06287e; } 239 | code > span.er { color: #ff0000; font-weight: bold; } 240 | 241 | -------------------------------------------------------------------------------- /source/focus4.md: -------------------------------------------------------------------------------- 1 | ## R.js -- 從 jStat 延伸出的開源 JavaScript 機率統計框架 2 | 3 | 我自從開始用 R 學習機率統計之後,就覺得這樣的科學計算平台真的很棒。 4 | 5 | 但可惜的是、我現在所使用的主力語言是 JavaScript,因為 JavaScript 是瀏覽器的唯一語言,而且有了 node.js 這樣的平台之後,可以通吃客戶端與伺服端兩方的應用。 6 | 7 | 於是我想要用 JavaScript 創造出一個類似 R 的環境,並且可以在 Web 上執行,所以就創造了 jsLab 專案。 8 | 9 | 但是、為了讓 jsLab 能支援那些機率統計功能,我必須尋找用 JavaScript 語言撰寫的機率統計函式庫。 10 | 11 | 在 2012 年我就注意到了 jStat 這個支援機率模型的函式庫,當時這個函式庫還有專屬的網站,但是現在這個函式庫連網站都不見了,還好在 github 裏還有一份原始碼,網址如下: 12 | 13 | * 14 | 15 | jStat 在機率模型的部分支援還算完整,但是在統計檢定的部分就相當薄弱,雖然也支援矩陣運算等功能,但是在 JavaScript 語言上, jStat 的矩陣運算支援並不算特別好的。 16 | 17 | 因此、我們決定將 jStat 重新包裝,成為一個新的 javascript 檔案,稱為 R.js ,這是 jsLab 專案的主要程式碼之一, R.js 的網址如下。 18 | 19 | * 20 | 21 | 您可以看到在 R.js 檔案裏,能夠呼叫 jStat 完成的部分,我們都盡可能的交給 jStat 來做,而 jStat 在這部份也確實做得很不錯。 22 | 23 | 檔案: R.js 24 | 25 | ```javascript 26 | ... 27 | // 均等分布 28 | R.runif=function(n, a, b) { return R.calls(n, jStat.uniform.sample, a, b); } 29 | R.dunif=function(x, a, b) { return jStat.uniform.pdf(x, a, b); } 30 | R.punif=function(q, a, b) { return jStat.uniform.cdf(q, a, b); } 31 | R.qunif=function(p, a, b) { return jStat.uniform.inv(p, a, b); } 32 | // 常態分布 33 | R.rnorm=function(n, mean, sd) { return R.calls(n, jStat.normal.sample, mean, sd); } 34 | R.dnorm=function(x, mean, sd) { return jStat.normal.pdf(x, mean, sd); } 35 | R.pnorm=function(q, mean, sd) { return jStat.normal.cdf(q, mean, sd); } 36 | // R.qnorm=function(p, mean, sd) { return R.q2x(p, function (q) { return R.pnorm(q, mean, sd);});} 37 | R.qnorm=function(p, mean, sd) { return jStat.normal.inv(p, mean, sd); } 38 | // 布瓦松分布 39 | R.rpois=function(n, l) { return R.calls(n, jStat.poisson.sample, l); } 40 | R.dpois=function(x, l) { return jStat.poisson.pdf(x, l); } 41 | R.ppois=function(q, l) { return jStat.poisson.cdf(q, l); } 42 | R.qpois=function(p, l) { return jStat.poisson.inv(p, l); } 43 | 44 | // F 分布 45 | R.rf=function(n, df1, df2) { return R.calls(n, jStat.centralF.sample, df1, df2); } 46 | R.df=function(x, df1, df2) { return jStat.centralF.pdf(x, df1, df2); } 47 | R.pf=function(q, df1, df2) { return jStat.centralF.cdf(q, df1, df2); } 48 | R.qf=function(p, df1, df2) { return jStat.centralF.inv(p, df1, df2); } 49 | // T 分布 50 | R.rt=function(n, dof) { return R.calls(n, jStat.studentt.sample, dof); } 51 | R.dt=function(x, dof) { return jStat.studentt.pdf(x, dof); } 52 | R.pt=function(q, dof) { return jStat.studentt.cdf(q, dof); } 53 | R.qt=function(p, dof) { return jStat.studentt.inv(p, dof); } 54 | ... 55 | ``` 56 | 57 | 不過、在離散的機率分布上面,jStat 就支援的比較不好,而且沒有支援像 inv 這類的函數,於是我們就得自己來補足,以下是我們用 jStat 與自己寫的程式所合成的一些離散分布原始碼。 58 | 59 | ```javascript 60 | ... 61 | R.sample1=function(a, p) { 62 | var r = Math.random(); 63 | var u = R.repeats(1.0, a.length); 64 | p = R.def(p, R.normalize(u)); 65 | var psum = 0; 66 | for (var i in p) { 67 | psum += p[i]; 68 | if (psum > r) 69 | return a[i]; 70 | } 71 | return null; 72 | } 73 | 74 | R.sample=function(x, n, p) { return R.calls(n, R.sample1, x, p); } 75 | 76 | // 二項分布 77 | R.rbinom=function(n, N, p) { return R.calls(n, jStat.binomial.sample, N, p); } 78 | R.dbinom=function(x, N, p) { return jStat.binomial.pdf(x, N, p); } 79 | R.pbinom=function(k, N, p) { return jStat.binomial.cdf(k, N, p); } 80 | R.qbinom=function(q, N, p) { 81 | for (var i=0; i<=N; i++) { 82 | if (R.pbinom(i, N, p) > q) return i; 83 | } 84 | return N; 85 | } 86 | 87 | // 負二項分布 88 | R.rnbinom=function(n, N, p) { return R.calls(n, jStat.negbin.sample, N, p); } 89 | R.dnbinom=function(x, N, p) { return jStat.negbin.pdf(x, N, p); } 90 | R.pnbinom=function(k, N, p) { return jStat.negbin.cdf(k, N, p); } 91 | // R.qnbinom=function(p, N, q) { return jStat.negbin.inv(p, N, q); } 92 | R.qnbinom=function(q, N, p) { 93 | for (var i=0; i q) return i; 95 | } 96 | return N; 97 | } 98 | ... 99 | ``` 100 | 101 | 另外、由於 jStat 在統計檢定方面的函數也很薄弱,所以我們撰寫了以下這個檢定的抽象函數,實作時只要補足「 q2p, o2q, h, df」等函數,就可以做出一個檢定功能了。 102 | 103 | ```javascript 104 | ... 105 | R.test = function(o) { // name, D, x, mu, sd, y, alpha, op 106 | var D = o.D; 107 | var x = o.x; 108 | var alpha = R.opt(o, "alpha", 0.05); 109 | o.op = R.opt(o, "op", "="); 110 | 111 | var pvalue, interval; 112 | var q1 = D.o2q(o); // 單尾檢定的 pvalue 113 | 114 | if (o.op === "=") { 115 | if (q1>0.5) q1 = 1-q1; // (q1>0.5) 取右尾,否則取左尾。 116 | pvalue= 2*q1; // 對稱情況:雙尾檢定的 p 值是單尾的兩倍。 117 | interval = [D.q2p(alpha/2, o, "L"), D.q2p(1-alpha/2, o, "R")]; 118 | } else { 119 | if (o.op === "<") { // 右尾檢定 H0: q < 1-alpha, 120 | interval = [ D.q2p(alpha, o, "L"), Infinity ]; 121 | pvalue = 1-q1; 122 | } 123 | if (o.op === ">") { // 左尾檢定 H0: q > alpha 124 | interval=[-Infinity, D.q2p(1-alpha, o, "R")]; 125 | pvalue = q1; 126 | } 127 | } 128 | 129 | return { name: o.name, 130 | h: D.h(o), 131 | alpha: alpha, 132 | op: o.op, 133 | pvalue: pvalue, 134 | ci : interval, 135 | df : D.df(o), 136 | report: function() { R.report(this) } 137 | }; 138 | } 139 | ... 140 | ``` 141 | 142 | 舉例而言,以下這個物件 t1 實作了 R.test 中所需要的函數,因此我們就可以透過「 `o.D = t1; t = R.test(o);` 這兩行指令呼叫 R.test 函數,完成單樣本的 t 檢定工作。 143 | 144 | ```javascript 145 | var t1 = { // 單樣本 T 檢定 t = (X-mu)/(S/sqrt(n)) 146 | h:function(o) { return "H0:mu"+o.op+o.mu; }, 147 | o2q:function(o) { 148 | var x = o.x, n = x.length; 149 | // t=(X-mu)/(sd/sqrt(n)) 150 | var t = (R.mean(x)-o.mu)/(R.sd(x)/Math.sqrt(n)); 151 | return R.pt(t, n-1); 152 | }, 153 | // P(X-mu/(S/sqrt(n)) X-t*S/sqrt(n)) = q ; 這反而成了右尾檢定,所以左尾與右尾確實會反過來 155 | q2p:function(q, o) { 156 | var x = o.x, n = x.length; 157 | return R.mean(x) + R.qt(q, n-1) * R.sd(x) / Math.sqrt(n); 158 | }, 159 | df:function(o) { return o.x.length-1; } 160 | } 161 | ... 162 | R.ttest = function(o) { 163 | var t; 164 | if (typeof o.y === "undefined") { 165 | o.name = "ttest(X)"; 166 | o.D = t1; 167 | t = R.test(o); 168 | t.mean = R.mean(o.x); 169 | t.sd = R.sd(o.x); 170 | } else { 171 | ``` 172 | 173 | 目前我們已經在 R.js 中加入了大部份的機率分布、還有基本的「有母數」檢定功能,之後會再加入「無母數檢定的功能」。 174 | 175 | 另外、我們也已經加入了基本的圖表繪製功能在 G.js 當中,於是形成了 jsLab 專案的基本架構,希望之後還能找到更多更棒的 JavaScript 科學計算函式庫,讓 JavaScript 語言也能 成為科學計算的良好平台。 176 | 177 | ### 參考文獻 178 | * 179 | * 180 | -------------------------------------------------------------------------------- /htm/article1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 |
36 | 39 |
40 |

d3.js -- 互動式繪圖框架

41 |

d3.js 是一個在瀏覽器裏使用的互動式繪圖框架,使用 HTML、CSS、JavaScript 與 SVG (Scalable Vector Graphics) 等技術。

42 |

d3.js 專案起始於 2011 年,是從 Protovis 專案修改過來的,通常我們會用 D3 來產生 SVG 或 CSS 的繪圖結果,在瀏覽器上檢視時還可以利用 SVG 或 CSS 與使用者進行互動。

43 |

d3.js 的用法有點像 jQuery,都是透過選擇器來進行選取後操作的,舉例而言、下列指令可以選出所有 p 標記的節點並將顏色修改為 lavender (淡紫色、熏衣草)。

44 |
 d3.selectAll("p")
 45 |    .style("color", "lavender");
46 |

我們可以透過「標記 tag、類別 class、代號 identifier、屬性 attribute、或位置 place 來選取節點,然後進行新增、刪除、修改等動作,然後透過設定 CSS 的轉移 (transition) 屬性,讓繪圖的結果可以和使用者進行互動,舉例而言、以下程式就會讓網頁裡的 p 標記節點逐漸地改變為紫色。 (d3.js 預設的改變速度為 250ms 完成轉換)

47 |
 d3.selectAll("p")
 48 |    .transition()
 49 |    .style("color", "pink");
50 |

由於 SVG 裏的標記也是 HTML 的一部分, d3 的指令也可以選取 SVG 裏的內容,以下來自 Mike Bostock 網站的 範例 顯示了這個狀況:

51 |
<svg width="720" height="120">
 52 |   <circle cx="40" cy="60" r="10"></circle>
 53 |   <circle cx="80" cy="60" r="10"></circle>
 54 |   <circle cx="120" cy="60" r="10"></circle>
 55 | </svg>
 56 | ...
 57 | <script>
 58 | var circle = d3.selectAll("circle");
 59 | circle.style("fill", "steelblue");
 60 | circle.attr("r", 30);
 61 | </script>
62 |

d3.js 的主要 API 包含下列幾類:

63 |
    64 |
  • Selections
  • 65 |
  • Transitions
  • 66 |
  • Arrays
  • 67 |
  • Math
  • 68 |
  • Color
  • 69 |
  • Scales
  • 70 |
  • SVG
  • 71 |
  • Time
  • 72 |
  • Layouts
  • 73 |
  • Geography
  • 74 |
  • Geometry
  • 75 |
  • Behaviors
  • 76 |
77 |

而以下的專案則是延伸自 d3.js 的套件,

78 |
    79 |
  • freeDataMap - Company data visualisation tool
  • 80 |
  • dimple.js - Flexible axis-based charting API
  • 81 |
  • Cubism - Time series visualisation
  • 82 |
  • Rickshaw - Toolkit for creating interactive time series graphs
  • 83 |
  • NVD3 - Re-usable charts for d3
  • 84 |
  • Crossfilter - Fast Multidimensional Filtering for Coordinated Views
  • 85 |
  • dc.js - Dimensional Charting Javascript Library
  • 86 |
  • c3.js - D3-based reusable chart library
  • 87 |
88 |

甚至還有人專門為 d3.js 寫了一本書,而且這本書還有中文版。

89 | 92 |

參考文獻

93 | 99 |
100 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /htm/article7.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

函數指標陣列 (Array of Function Pointers) (作者:研發養成所 Bridan)

41 |

函數指標陣列,這是一種 C/C++ 程式語言的高階設計技巧,希望能有較高的執行效能。 我以 Arduino 當作測試平台,比較兩種程式設計技巧,發現與我的認知有些差異。

42 |

先看傳統設計方式,用 switch case 執行不同功能:

43 |
//
 44 | // Author: Bridan
 45 | //         http://4rdp.blogspot.com
 46 | // Date:   2014/09/27
 47 | //
 48 | // Brief:  Test switch case
 49 | //
 50 | 
 51 | void setup() {
 52 |   Serial.begin(9600);
 53 |   while (!Serial) {
 54 |     ; // wait for serial port to connect. Needed for Leonardo only
 55 |   }
 56 | 
 57 |   TCCR1A = 0x00;                // Normal mode, just as a Timer
 58 |   TCCR1B &= ~_BV(CS12);         // no prescaling
 59 |   TCCR1B &= ~_BV(CS11);      
 60 |   TCCR1B |= _BV(CS10);   
 61 | }
 62 | 
 63 | void loop() {
 64 |   byte i;
 65 | 
 66 |   TCNT1 = 0;     // reset timer
 67 |   for (i=0 ; i<3 ; i++) {
 68 |     switch (i) {
 69 |       case 0:
 70 |         Serial.println("CASE 0");
 71 |         break;
 72 |       case 1:
 73 |         Serial.println("CASE 1");
 74 |         break;
 75 |       case 2:
 76 |         Serial.println("CASE 2");
 77 |         break;
 78 |     }
 79 |   }
 80 |   Serial.println(TCNT1);
 81 | }
82 |

switch case 3 個時,編譯 2410 bytes,執行 6092 ~ 6100 timer clock switch case 4 個時,編譯 2430 bytes,執行 8136 ~ 8146 timer clock switch case 5 個時,編譯 2458 bytes,執行 10185 ~ 10195 timer clock

83 |

將上面程式修改成函數指標陣列,以查表方式直接跳到執行的程式:

84 |
//
 85 | // Author: Bridan
 86 | //         http://4rdp.blogspot.com
 87 | // Date:   2014/09/27
 88 | //
 89 | // Brief:  Test Array of Function Pointers
 90 | //
 91 | 
 92 | void setup() {
 93 |   Serial.begin(9600);
 94 |   while (!Serial) {
 95 |     ; // wait for serial port to connect. Needed for Leonardo only
 96 |   }
 97 | 
 98 |   TCCR1A = 0x00;                // Normal mode, just as a Timer
 99 |   TCCR1B &= ~_BV(CS12);         // no prescaling
100 |   TCCR1B &= ~_BV(CS11);      
101 |   TCCR1B |= _BV(CS10);   
102 | }
103 | 
104 | void FUNC0(void) {
105 |      Serial.println("CASE 0");
106 | }
107 | void FUNC1(void) {
108 |      Serial.println("CASE 1");
109 | }
110 | void FUNC2(void) {
111 |      Serial.println("CASE 2");
112 | }
113 | 
114 | void (*TABLE_JUMP[])(void) = {
115 |   FUNC0,
116 |   FUNC1,
117 |   FUNC2
118 | };
119 | 
120 | void loop() {
121 |   byte i;
122 | 
123 |   TCNT1 = 0;     // reset timer
124 |   for (i=0 ; i<3 ; i++) {
125 |     (*TABLE_JUMP[i])();
126 |   }
127 |   Serial.println(TCNT1);
128 | }
129 |

TABLE 3 個時,編譯 2438 bytes,執行 6082 ~ 6096 timer clock TABLE 4 個時,編譯 2470 bytes,執行 8130 ~ 8142 timer clock TABLE 5 個時,編譯 2504 bytes,執行 10176 ~ 10194 timer clock

130 |

以往我所用過的 compiler,switch case 相當於很多 if ... else ... 的組合,條件一個一個比較,數值越大的條件,花費比較的時間越多,以上面的例子在比較方面所費的時間 = 1 + 2 + 3 + ... + N,而函數指標陣列查表時間約 = 1 x N,比 switch case 有效率,這部分與結果相符 (比較條件太少,不易看出差異)。

131 |

至於程式碼大小,發現越多條件狀況,以函數指標陣列方式設計比 switch case 程式碼多?因為不清楚 Arduino compiler 如何設計,無法進一步評論,但直覺 Arduino compiler 缺少這方面最佳化處理。

132 |
133 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /htm/article4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

CodeMirror -- 有 IntelliSense 功能的網頁版開源編輯器

41 |

在建構 jsLab 科學計算平台的過程中,由於要讓使用者在 JavaScript 程式編輯上有更好的感受,而不是只能依賴死板板的 textarea 區塊,所以我們找了幾個用 javascript 建構的網頁版程式碼編輯器,像是 Ace、Atom、EditArea 與 CodeMirror 等專案,最後我們認為 CodeMirror 最適合我們使用,因為 CodeMirror 的資源完整,而且具有支援 JavaScript 語言 IntelliSense 功能的插件。

42 | 48 |

CodeMirror 支援超過六十種語言的上色與編輯功能,包含 HTML、XML、Javascript、Python、Ruby、C/C++/C#、.... 等等,您可以參考下列網頁。

49 | 52 |

另外、 CodeMirror 還支援了下列的特色功能。

53 |
    54 |
  • A powerful, composable language mode system
  • 55 |
  • Autocompletion (XML)
  • 56 |
  • Code folding
  • 57 |
  • Configurable keybindings
  • 58 |
  • Vim, Emacs, and Sublime Text bindings
  • 59 |
  • Search and replace interface
  • 60 |
  • Bracket and tag matching
  • 61 |
  • Support for split views
  • 62 |
  • Linter integration
  • 63 |
  • Mixing font sizes and styles
  • 64 |
  • Various themes
  • 65 |
  • Able to resize to fit content
  • 66 |
  • Inline and block widgets
  • 67 |
  • Programmable gutters
  • 68 |
  • Making ranges of text styled, read-only, or atomic
  • 69 |
  • Bi-directional text support
  • 70 |
  • Many other methods and addons...
  • 71 |
72 |

其中我們最需要的是 JavaScript 的 Intellisense 功能,該功能的範例網址如下:

73 | 76 |

可惜的是,該範例使用 Ctrl-Space 做為 Intellisense 的功能鍵,但是這個按鍵與繁體中文 windows 的輸入法切換功能相衝,所以沒辦法正常運作,因此我們將該範例的 「Ctrl-Space」 改為 「Ctrl-.」 ,以避免這種衝突的情況,修改版的範例的網址與程式碼如下。

77 | 80 |
<!doctype html>
 81 | 
 82 | <title>CodeMirror: Autocomplete Demo</title>
 83 | <meta charset="utf-8"/>
 84 | <link rel=stylesheet href="../doc/docs.css">
 85 | 
 86 | <link rel="stylesheet" href="../lib/codemirror.css">
 87 | <link rel="stylesheet" href="../addon/hint/show-hint.css">
 88 | <script src="../lib/codemirror.js"></script>
 89 | <script src="../addon/hint/show-hint.js"></script>
 90 | <script src="../addon/hint/javascript-hint.js"></script>
 91 | <script src="../mode/javascript/javascript.js"></script>
 92 | 
 93 | <div id=nav>
 94 |   <a href="http://codemirror.net"><img id=logo src="../doc/logo.png"></a>
 95 | 
 96 |   <ul>
 97 |     <li><a href="../index.html">Home</a>
 98 |     <li><a href="../doc/manual.html">Manual</a>
 99 |     <li><a href="https://github.com/marijnh/codemirror">Code</a>
100 |   </ul>
101 |   <ul>
102 |     <li><a class=active href="#">Autocomplete</a>
103 |   </ul>
104 | </div>
105 | 
106 | <article>
107 | <h2>Autocomplete Demo</h2>
108 | <form><textarea id="code" name="code">
109 | function getCompletions(token, context) {
110 |   var found = [], start = token.string;
111 |   function maybeAdd(str) {
112 |     if (str.indexOf(start) == 0) found.push(str);
113 |   }
114 |   function gatherCompletions(obj) {
115 |     if (typeof obj == "string") forEach(stringProps, maybeAdd);
116 |     else if (obj instanceof Array) forEach(arrayProps, maybeAdd);
117 |     else if (obj instanceof Function) forEach(funcProps, maybeAdd);
118 |     for (var name in obj) maybeAdd(name);
119 |   }
120 | 
121 |   if (context) {
122 |     // If this is a property, see if it belongs to some object we can
123 |     // find in the current environment.
124 |     var obj = context.pop(), base;
125 |     if (obj.className == "js-variable")
126 |       base = window[obj.string];
127 |     else if (obj.className == "js-string")
128 |       base = "";
129 |     else if (obj.className == "js-atom")
130 |       base = 1;
131 |     while (base != null && context.length)
132 |       base = base[context.pop().string];
133 |     if (base != null) gatherCompletions(base);
134 |   }
135 |   else {
136 |     // If not, just look in the window object and any local scope
137 |     // (reading into JS mode internals to get at the local variables)
138 |     for (var v = token.state.localVars; v; v = v.next) maybeAdd(v.name);
139 |     gatherCompletions(window);
140 |     forEach(keywords, maybeAdd);
141 |   }
142 |   return found;
143 | }
144 | </textarea></form>
145 | 
146 | <p>Press <strong>ctrl-.</strong> to activate autocompletion. Built
147 | on top of the <a href="../doc/manual.html#addon_show-hint"><code>show-hint</code></a>
148 | and <a href="../doc/manual.html#addon_javascript-hint"><code>javascript-hint</code></a>
149 | addons.</p>
150 | 
151 |     <script>
152 |       var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
153 |         lineNumbers: true,
154 |         extraKeys: {"Ctrl-.": "autocomplete"},
155 |         mode: {name: "javascript", globalVars: true}
156 |       });
157 |     </script>
158 |   </article>
159 |

不過、雖然 CodeMirror 支援了 JavaScript 的 Intellisense 功能,但是卻不徹底,對於像是字串之類的語法,他可以顯示提示函數與訊息,但對於變數的部分,卻無法正確提示,以下是一個可以正確提示的範例。

160 |
161 | 圖、CodeMirror 可以正確提示的 JavaScript 編輯範例

圖、CodeMirror 可以正確提示的 JavaScript 編輯範例

162 |
163 |

如果需要更進一步的正確提示功能,恐怕還是得修改 CodeMirror 的 ../addon/hint/javascript-hint.js 模組才行。

164 |

雖然 CodeMirror 已經算不錯了,不過我想還有進步空間,但大體來說 CodeMirror 已經是很好的網頁程式編輯器了。

165 |

不過、如果您需要的是可以加上「粗體、斜體、字型、超連結、....」等功能,那就不是 CodeMirror 所具備的功能了,這種功能是 RichText Editor 才具備的,您可以參考下列文章中的 RichText 編輯器。

166 | 169 |

參考文獻

170 | 174 |
175 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /htm/focus3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

「JsLab 科學計算平台」背後的開放原始碼結構

41 |

為了要用 JavaScript 建構出科學計算平台,我們創建了以下的 JsLab 開放原始碼專案。

42 | 45 |

我們大量的採用了 JavaScript 的開放原始碼函式庫,像是在「機率統計」領域採用了 jStat 這個專案,在繪圖領域採用了 d3.js、c3.js、vis.js 等等,這些專案的網址如下。

46 | 52 |

JsLab 科學計算平台的核心,是一組基於 jStat 專案的重新封裝,我們將 jStat 重新封裝成類似 R 函式庫的介面,並且加上了一些 jStat 當中所沒有的功能,特別是統計檢定的部份,形成了 R.js 這個 JavaScript 程式,讓 JavaScript 也能擁有類似 R 軟體的機率統計函式庫。

53 |

我們雖然使用了 d3.js 這個繪圖函式庫進行 2D 繪圖,但由於 d3.js 並不容易使用,所以我們採用了 c3.js 這個基於 d3 的延伸套件,簡化 d3 繪圖函式庫的使用,讓我們不需瞭解太多繪圖的細節就能寫出 JsLab 的繪圖函式庫。

54 |

舉例而言、下列的圖形就是依靠 c3.js 所繪製的,只不過我們將 c3.js 進一步封裝到 JsLab 的 G.js 這個的繪圖函式庫當中而已。

55 |
56 | 57 |
58 |

以下是我們將 c3.js 重新封裝成 G.js 的程式碼片段。

59 |

檔案: G.js

60 |
var C3G=function() {
 61 |   this.g = {
 62 |         data: {
 63 |           xs: {},
 64 |           columns: [ /*["x", 1, 2, 3, 4 ]*/ ],
 65 |           type: "line", 
 66 |           types : {}
 67 |         },
 68 |         axis: {
 69 |           x: {
 70 |             label: 'X',
 71 |             tick: { fit: false, format:d3.format(".2f") }
 72 |           },
 73 |           y: { label: 'Y', 
 74 |             tick : { format: d3.format(".2f") }
 75 |           }
 76 |         }, 
 77 |         bar: { width: { ratio: 0.9 } }, 
 78 |       };
 79 |   this.varcount = 0;
 80 |   this.xrange(-10, 10);
 81 |   this.step = 1;
 82 |   this.setrange = false;
 83 | }
 84 | ....
 85 | C3G.prototype.hist = function(x, options) {
 86 |   var name = R.opt(options, "name", this.tempvar()); 
 87 |   var mode = R.opt(options, "mode", ""); 
 88 |   var step = R.opt(options, "step", this.step); 
 89 |   var from = R.opt(options, "from", this.xmin); 
 90 |   var to   = R.opt(options, "to", this.xmax);
 91 |   this.g.data.types[name] = "bar";
 92 |   this.g.data.xs[name] = name+"x";
 93 |   var xc = R.steps(from+step/2.0, to, step);
 94 |   var n = (to-from)/step + 1;
 95 |   var count = R.repeats(0, n);
 96 |   for (var i in x) {
 97 |     var slot=Math.floor((x[i]-from)/step);
 98 |     if (slot>=0 && slot < n)
 99 |       count[slot]++;
100 |   }
101 |   this.g.data.columns.push([name+"x"].concat(xc));
102 |   var total = R.sum(count);
103 |   if (mode === "normalized")
104 |     count = R.apply(count, function(c) { return (1.0/step)*(c/total); });
105 |   this.g.data.columns.push([name].concat(count));
106 | }
107 | ...
108 | C3G.prototype.show = function() {
109 |   if (typeof(module)==="undefined")
110 |     return c3.generate(this.g);
111 | }
112 |

另外、由於 d3.js 並沒有支援 3D 曲面圖形的繪製,所以我們又引入了 vis.js 這個繪圖函式庫來完成 3D 圖形的繪製工作。

113 |

以下是我們將 vis.js 封裝成 G.js 的程式碼片段

114 |

檔案: G.js

115 |
...
116 | VISG.prototype.curve3d = function(f, box) {
117 |   // Create and populate a data table.
118 |   var data = new vis.DataSet();
119 |   // create some nice looking data with sin/cos
120 |   var counter = 0;
121 |   var steps = 50;  // number of datapoints will be steps*steps
122 |   var axisMax = 314;
123 |   var axisStep = axisMax / steps;
124 |   for (var x = 0; x < axisMax; x+=axisStep) {
125 |     for (var y = 0; y < axisMax; y+=axisStep) {
126 |       var value = f(x,y);
127 |       data.add({id:counter++,x:x,y:y,z:value,style:value});
128 |     }
129 |   }
130 |   this.graph = new vis.Graph3d(box, data, this.options);
131 | }
132 | ...
133 | G.curve3d = function(f) {
134 |   G.visg.curve3d(f, G.box);
135 | }
136 |

接著、為了讓使用者編輯程式可以更容易,我們採用了這個 JavaScript 開源線上編輯器專案,該專案之援類似微軟 Visual Studio 的 IntelliSense 這樣的函數提示功能,

137 | 140 |
141 | 圖、JsLab 當中的程式碼上色與 IntelliSense 功能

圖、JsLab 當中的程式碼上色與 IntelliSense 功能

142 |
143 |

以下是我們將 codemirror 封裝成 E.js (Editor) 的完整程式碼。

144 |

檔案: E.js

145 |
"use strict";
146 | 
147 | U.use("../js/codemirror/lib/codemirror.js", "CodeMirror");
148 | U.use("../js/codemirror/addon/hint/show-hint.js");
149 | U.use("../js/codemirror/addon/hint/javascript-hint.js");
150 | U.use("../js/codemirror/mode/javascript/javascript.js");
151 | 
152 | E = {};
153 | 
154 | if (typeof module!=="undefined") module.exports = E;
155 | 
156 | E.editor = null;
157 | 
158 | E.loadEditor = function(codebox) {
159 |   E.codebox = codebox;
160 |   E.editor = CodeMirror.fromTextArea(codebox, {
161 |     lineNumbers: true,
162 |     extraKeys: {"Ctrl-.": "autocomplete"},
163 |     lineWrapping: true, 
164 |     styleActiveLine: true,
165 |     mode: {name: "javascript", globalVars: true}
166 |   });
167 |   
168 |   E.editor.on('update', function(instance){
169 |     E.codebox.value = instance.getValue();
170 |   });  
171 | }
172 |

未來、我們可能會進一步整合更多的函式庫,目前預計在「矩陣運算領域」會採用了 jStat 與 numeric.js 等函式庫,而在數位訊號語音處理領域可能會採用 DSP.js,影像處理領域可能採用 CamanJS 等等,這些函式庫的網址如下:

173 | 178 |

目前、網路上的 JavaScript 的函式庫還持續的急速增長中,我們相信之後會有更多更好用的 JavaScript 科學計算函式庫出現,我們只要能將這些好用的函式庫整合進來,就能創建一個完整的科學計算平台了,而這也正是 JsLab 計劃所想要達成的目標。

179 |

由於 JavaScript 是瀏覽器當中唯一能使用的官方語言,因此我們認為未來 JavaScript 的發揮空間將會越來越大,就像 Jeff Atwood 在 2007 年所提出的 Atwood's Law 所說的:

180 |
181 |

Any application that can be written in JavaScript, will eventually be written in JavaScript.

182 |
183 |

換句話說 -- 「任何可以寫成 JavaScript 的應用程式,最後都會被寫成 JavaScript」。

184 |

如果 Atwood's Law 成立的話,那基於 JavaScript 的科學計算平台就應該要出現啊!

185 |

我們正在以行動來實現 Atwood 的話,這個行動的代號就是 JsLab 。

186 |

參考文獻

187 | 190 |
191 | 194 | 195 | 196 | -------------------------------------------------------------------------------- /source/focus2.md: -------------------------------------------------------------------------------- 1 | ## JsLab -- JavaScript 版的科學計算平台 2 | 3 | 雖然已經有很多科學計算軟體,像是 MatLab、 Mathematica、SPSS、SAS 等等,而且也有像 R、Octave、SciPy 等開放原始碼的科學計算軟體,但就是沒有以 JavaScript 為主的科學計算軟體。 4 | 5 | 於是我們決定要用 JavaScript 建構一個科學計算軟體,所以、JsLab 計劃就誕生了,關於 JsLab 的用法,可以參考下列的展示影片。 6 | 7 | * [展示影片:jslab -- 一個像 R 的 JavaScript 數學實驗環境](https://www.youtube.com/watch?v=v-lAsFm1zwQ) 8 | 9 | 下圖是我們已經上傳到 github 上的 JsLab 專案之執行畫面,該程式是一個純粹用 HTML+JavaScript 建構的網頁,網址如下: 10 | 11 | * 12 | 13 | 您可以連結到該網頁上直接使用該平台,雖然現在還沒有很強大,不過已經可以使用了。 14 | 15 | ![圖、JsLab 的執行畫面 -- 繪製 3D 函數圖](../img/JsLab.jpg) 16 | 17 | 在上述網頁中,我預設在編輯器裏放入了一個展示程式如下, JsLab 會執行該程式後將結果放在訊息視窗,並將繪圖部份顯示在右邊的窗框中。 18 | 19 | 檔案: curve3D.js 20 | 21 | ```javascript 22 | function f(x, y) { 23 | return (Math.sin(x/50) * Math.cos(y/50) * 50 + 50); 24 | } 25 | G.curve3d(f); 26 | ``` 27 | 28 | 您可以將程式貼到該網頁的程式編輯區,然後按下執行即可得到執行結果。舉例而言、您可以貼上下列程式到編輯區。 29 | 30 | 檔案: curveT.js 31 | 32 | ```javascript 33 | G.curve(fx(dt, 3), {name:"dt(3)", step:0.1}); 34 | G.curve("dt(x,10)",{name:"dt(10)", step:0.1}); 35 | G.curve(fx(dt, 25),{name:"dt(25)", step:0.1}); 36 | ``` 37 | 38 | 然後按下執行的 run 按鈕,就可以看到下列的曲線圖。 39 | 40 | ![圖、JsLab 的執行畫面 -- 繪製 2D 曲線圖](../img/JsLabCurve.jpg) 41 | 42 | 或者您也可以將下列程式貼到程式區,然後按下執行的 run 按鈕,就可以看到所繪出的散點圖。 43 | 44 | 檔案: plot1.js 45 | 46 | ```javascript 47 | Ax = R.rnorm(100, 10, 1); 48 | Ay = R.rnorm(100, 0, 0.5); 49 | Bx = R.rnorm(100, 0, 1); 50 | By = R.rnorm(100, 0, 0.5); 51 | G.plot(Ax, Ay, {name:"A"}); 52 | G.plot(Bx, By, {name:"B"}); 53 | ``` 54 | 55 | ![圖、JsLab 的執行畫面 -- 隨機取樣後繪製散點圖](../img/JsLabPlot.jpg) 56 | 57 | 當然、如果您將程式存檔在自己的電腦,那麼您也可以按下「選擇檔案」的按鈕,接著選取想要執行的檔案,就可以將程式上傳並執行,以下是我們透過上傳的方式執行 hist.js 程式的結果。 58 | 59 | 檔案: hist.js 60 | 61 | ```javascript 62 | var x = rnorm(1000, 5, 2); 63 | G.hist(x, {name:"x", mode:"normalized"}); 64 | G.curve("dnorm(x, 5,2)", {name:"N(5,2)", step:0.2}); 65 | ``` 66 | 67 | ![圖、JsLab 的執行畫面 -- 隨機取樣後繪製統計長條圖](../img/JsLabHist.jpg) 68 | 69 | 如果您並不想使用瀏覽器介面,也不需要繪製圖形,那麼您也可以採用 node.js 的命令列執行方式,直接引用 JsLab 背後的函式庫,像是 R.js 進行科學計算的動作,以下是我們在 node.js 中使用 R.js 進行隨機抽樣的一個範例。 70 | 71 | 檔案: sample.js 72 | 73 | ```javascript 74 | var U = require("../source/U"); 75 | U.use("../source/R", "R"); 76 | 77 | log("=======二項分布測試==========="); 78 | log("pbinom(7, 12, 0.4)="+pbinom(7, 12, 0.4)); // > pbinom(7, 12, 0.4) [1] 0.9426901 79 | log("qbinom(0.9, 12, 0.4)="+qbinom(0.9, 12, 0.4)); // > qbinom(0.9, 12, 0.4)[1] 7 80 | log("qbinom(0.95, 12, 0.4)="+qbinom(0.95, 12, 0.4)); // > qbinom(0.95, 12, 0.4)[1] 8 81 | 82 | log("=======常態分布抽樣==========="); 83 | log("rnorm="+rnorm); 84 | log("rnorm(5, 2, 1)="+str(rnorm(5,2,1))); 85 | var y = rnorm(25, 0, 2); 86 | log("y="+str(y)); 87 | 88 | log("=======模擬丟銅板 100 次==========="); 89 | log("sample([正, 反], 100)="+sample(["正", "反"], 100)); 90 | 91 | log("=======模擬擲骰子 100 次==========="); 92 | log("sample([1,2,3,4,5,6], 100)="+sample([1,2,3,4,5,6], 100)); 93 | 94 | ``` 95 | 96 | 執行結果 97 | 98 | ``` 99 | D:\Dropbox\Public\jslab\test>node sample.js 100 | use ../source/R name=R 101 | use ../js/jstat.js name=jStat 102 | =======二項分布測試=========== 103 | pbinom(7, 12, 0.4)=0.9426900787200003 104 | qbinom(0.9, 12, 0.4)=7 105 | qbinom(0.95, 12, 0.4)=8 106 | =======常態分布抽樣=========== 107 | rnorm=function (n, mean, sd) { return R.calls(n, jStat.normal.sample, mean, sd); 108 | } 109 | rnorm(5, 2, 1)=[2.0748,2.3562,3.014,3.6833,4.1393] 110 | y=[-0.3756,1.2935,-1.9635,0.5446,0.6514,2.7079,-1.2434,-4.8451,1.0937,2.5094,0.1 111 | 423,4.6915,1.3294,-1.3275,1.0153,2.5058,-2.5361,1.7784,3.908,-2.2349,0.186,-2.17 112 | 17,-1.4398,0.0423,1.2014] 113 | =======模擬丟銅板 100 次=========== 114 | sample([正, 反], 100)=正,正,反,反,正,正,反,正,反,反,正,正,反,反,正,正,正,反,反, 115 | 正,反,正,反,反,反,反,正,正,正,反,反,反,正,反,正,反,反,正,反,正,正,正,反,正,反,反 116 | ,正,反,反,正,正,正,正,正,正,正,正,正,反,反,正,正,反,反,反,反,反,反,正,反,反,正, 117 | 反,正,反,反,正,反,正,反,反,反,正,正,反,反,正,正,正,正,反,正,反,反,正,正,反,反,反 118 | ,正 119 | =======模擬擲骰子 100 次=========== 120 | sample([1,2,3,4,5,6], 100)=3,2,4,6,5,2,4,4,5,5,1,5,1,1,2,1,4,1,1,2,1,4,1,6,1,4,6 121 | ,5,1,4,1,6,1,1,2,6,1,5,1,3,3,1,3,4,2,5,6,4,3,5,2,4,3,1,2,1,6,3,2,4,1,2,1,4,2,6,3 122 | ,5,4,5,4,4,1,4,2,6,2,4,5,2,3,5,1,3,3,2,3,2,1,3,5,3,2,5,3,6,2,4,1,2 123 | ``` 124 | 125 | 另外、目前我們也還持續的在增加 JsLab 函式庫的功能,像是我們正在為 R.js 加上各種統計檢定的功能,以下是採用 node.js 環境執行檢定的一些案例。 126 | 127 | 由於 jStat 函式庫並沒有支援這些統計檢定的函數,因此筆者只好自行撰寫,為了撰寫這些檢定的程式,我甚至將 R 的原始碼給翻了出來,網址如下: 128 | 129 | * 130 | 131 | 以下是我們對這些檢定功能的一些測試範例,大部分的功能都有對應的 R 操作與執行結果,這樣我們就能利用 R 軟體來驗證我們所寫的檢定函數是否正確了。 132 | 133 | 檔案: rtest.js 134 | 135 | ```javascript 136 | var U = require("../source/U"); 137 | U.use("../source/R", "R"); 138 | 139 | // x = rnorm(10, 5, 2) 140 | var x = [7.169890 ,2.188864 , 2.963868 ,7.790631 ,2.474261 ,7.694849 ,1.585007 ,4.087697 ,3.051643 ,4.697559]; 141 | // y = rnorm(10, 4,2) 142 | var y = [4.9627295,6.0336209,-0.4610221,7.3744023,2.4804347,7.2053190,3.5558563,3.6505476,2.2200754,5.3021459]; 143 | // py = x + rnorm(10, 1, 2) 144 | var py= [9.829046 ,2.491387 ,6.037504 ,5.709755 ,5.461208 ,7.345603 ,3.040538 ,4.856838 ,3.195437 ,7.079105]; 145 | 146 | log("x="+str(x)); 147 | log("y="+str(y)); 148 | 149 | ttest({x:x, mu:6, alpha:0.05, op:"="}).report(); 150 | 151 | /* 152 | > t.test(x, mu=6, alpha=0.05) 153 | 154 | One Sample t-test 155 | 156 | data: x 157 | t = -2.1732, df = 9, p-value = 0.05781 158 | alternative hypothesis: true mean is not equal to 6 159 | 95 percent confidence interval: 160 | 2.674155 6.066699 161 | sample estimates: 162 | mean of x 163 | 4.370427 */ 164 | 165 | ttest({x:x, mu:6, alpha:0.05, op:"<"}).report(); 166 | 167 | /* 168 | > t.test(x, mu=6, alternative="greater") 169 | 170 | One Sample t-test 171 | 172 | data: x 173 | t = -2.1732, df = 9, p-value = 0.9711 174 | alternative hypothesis: true mean is greater than 6 175 | 95 percent confidence interval: 176 | 2.995873 Inf 177 | sample estimates: 178 | mean of x 179 | 4.370427 180 | */ 181 | 182 | ttest({x:x, mu:6, alpha:0.05, op:">"}).report(); 183 | 184 | /* 185 | > t.test(x, mu=6, alternative="less") 186 | 187 | One Sample t-test 188 | 189 | data: x 190 | t = -2.1732, df = 9, p-value = 0.02891 191 | alternative hypothesis: true mean is less than 6 192 | 95 percent confidence interval: 193 | -Inf 5.744981 194 | sample estimates: 195 | mean of x 196 | 4.370427 197 | */ 198 | 199 | ztest({x:x, mu:6, sd:2.5, alpha:0.05, op:"="}).report(); 200 | 201 | ttest({x:x, y:y, mu:1, alpha:0.05, varequal:true, op:"="}).report(); 202 | 203 | /* 204 | > t.test(x, y, mu=1, conf.level=0.95, var.equal=T, alternative="two.sided"); 205 | 206 | Two Sample t-test 207 | 208 | data: x and y 209 | t = -0.8012, df = 18, p-value = 0.4335 210 | alternative hypothesis: true difference in means is not equal to 1 211 | 95 percent confidence interval: 212 | -2.122363 2.398395 213 | sample estimates: 214 | mean of x mean of y 215 | 4.370427 4.232411 */ 216 | 217 | ttest({x:x, y:py, mu:-1, alpha:0.05, paired:true, op:"="}).report(); 218 | 219 | /* 220 | > t.test(x, py, mu=-1, conf.level=0.95, paired=T) 221 | 222 | Paired t-test 223 | 224 | data: x and py 225 | t = -0.252, df = 9, p-value = 0.8067 226 | alternative hypothesis: true difference in means is not equal to -1 227 | 95 percent confidence interval: 228 | -2.33885689 0.07042649 229 | sample estimates: 230 | mean of the differences 231 | -1.134215 */ 232 | 233 | ttest({x:x, y:y, mu:1, alpha:0.05, op:"="}).report(); 234 | 235 | /* 236 | > t.test(x, y, mu=1, conf.level=0.95, alternative="two.sided"); 237 | 238 | Welch Two Sample t-test 239 | 240 | data: x and y 241 | t = -0.8012, df = 17.985, p-value = 0.4335 242 | alternative hypothesis: true difference in means is not equal to 1 243 | 95 percent confidence interval: 244 | -2.122495 2.398527 245 | sample estimates: 246 | mean of x mean of y 247 | 4.370427 4.232411 248 | */ 249 | 250 | ftest({x:x, y:y}).report(); 251 | 252 | /* 253 | > var.test(x,y) 254 | 255 | F test to compare two variances 256 | 257 | data: x and y 258 | F = 0.9445, num df = 9, denom df = 9, p-value = 0.9337 259 | alternative hypothesis: true ratio of variances is not equal to 1 260 | 95 percent confidence interval: 261 | 0.2346094 3.8026974 262 | sample estimates: 263 | ratio of variances 264 | 0.9445362 265 | */ 266 | 267 | var vx = [175, 176, 173, 175, 174, 173, 173, 176, 173, 179]; 268 | vartest({x:vx, sd:2, alpha:0.05, op:"="}).report(); 269 | // R 軟體沒有此函數,測試請看湯銀才 143 頁 270 | // 信賴區間 (1.793, 12.628) 271 | 272 | binomtest({x:7, n:12, p:0.4, op:">"}).report(); 273 | 274 | /* 275 | > binom.test(x=7, n=12, p=0.4, alternative="less") 276 | 277 | Exact binomial test 278 | 279 | data: 7 and 12 280 | number of successes = 7, number of trials = 12, p-value = 0.9427 281 | alternative hypothesis: true probability of success is less than 0.4 282 | 95 percent confidence interval: 283 | 0.0000000 0.8189752 284 | sample estimates: 285 | probability of success 286 | 0.5833333 287 | */ 288 | 289 | binomtest({x:7, n:12, p:0.4, op:"<"}).report(); 290 | /* 291 | > binom.test(x=7, n=12, p=0.4, alternative="greater") 292 | 293 | Exact binomial test 294 | 295 | data: 7 and 12 296 | number of successes = 7, number of trials = 12, p-value = 0.1582 297 | alternative hypothesis: true probability of success is greater than 0.4 298 | 95 percent confidence interval: 299 | 0.3152378 1.0000000 300 | sample estimates: 301 | probability of success 302 | 0.5833333 303 | */ 304 | 305 | 306 | 307 | binomtest({x:7, n:12, p:0.4}).report(); // 有誤,p-value 與 R 不同 308 | 309 | /* 310 | > binom.test(x=7, n=12, p=0.4) 311 | 312 | Exact binomial test 313 | 314 | data: 7 and 12 315 | number of successes = 7, number of trials = 12, p-value = 0.2417 ==> R.js ??? error : pvalue : 0.1146 316 | alternative hypothesis: true probability of success is not equal to 0.4 317 | 95 percent confidence interval: 318 | 0.2766697 0.8483478 319 | sample estimates: 320 | probability of success 321 | 0.5833333 322 | */ 323 | 324 | 325 | proptest({x:91, n:100, p:0.9, correct:false}).report(); 326 | 327 | /* 1-sample proportions test without continuity correction 328 | 329 | data: 91 out of 100, null probability 0.9 330 | X-squared = 0.1111, df = 1, p-value = 0.7389 331 | alternative hypothesis: true p is not equal to 0.9 332 | 95 percent confidence interval: 333 | 0.8377379 0.9519275 334 | sample estimates: 335 | p 336 | 0.91 */ 337 | 338 | proptest({x:23, n1:102, y:25, n2:135, correct:false}).report(); 339 | 340 | /* 341 | > success = c(23, 25) 342 | > total = c(102, 135) 343 | > prop.test(success, total) 344 | 345 | 2-sample test for equality of proportions with continuity correction 346 | 347 | data: success out of total 348 | X-squared = 0.3615, df = 1, p-value = 0.5477 349 | alternative hypothesis: two.sided 350 | 95 percent confidence interval: 351 | -0.07256476 0.15317478 352 | sample estimates: 353 | prop 1 prop 2 354 | 0.2254902 0.1851852 355 | */ 356 | 357 | proptest({x:8, n1:100, y:12, n2:200, op:"<", correct:false}).report(); 358 | 359 | /* 360 | > prop.test(c(8,12), c(100,200), alternative="greater", correct=F) 361 | 362 | 2-sample test for equality of proportions without continuity 363 | correction 364 | 365 | data: c(8, 12) out of c(100, 200) 366 | X-squared = 0.4286, df = 1, p-value = 0.2563 367 | alternative hypothesis: greater 368 | 95 percent confidence interval: 369 | -0.03248088 1.00000000 => R.js ??? [-0.0303,Infinity] 370 | sample estimates: 371 | prop 1 prop 2 372 | 0.08 0.06 373 | */ 374 | ``` 375 | 376 | 執行結果 377 | 378 | ``` 379 | D:\Dropbox\Public\jslab\test>node rtest 380 | use ../source/R name=R 381 | use ../js/jstat.js name=jStat 382 | x=[7.1699,2.1889,2.9639,7.7906,2.4743,7.6948,1.585,4.0877,3.0516,4.6976] 383 | y=[4.9627,6.0336,-0.461,7.3744,2.4804,7.2053,3.5559,3.6505,2.2201,5.3021] 384 | =========== report ========== 385 | name : "ttest(X)" 386 | h : "H0:mu=6" 387 | alpha : 0.05 388 | op : "=" 389 | pvalue : 0.0578 390 | ci : [2.6742,6.0667] 391 | df : 9 392 | mean : 4.3704 393 | sd : 2.3712 394 | =========== report ========== 395 | name : "ttest(X)" 396 | h : "H0:mu<6" 397 | alpha : 0.05 398 | op : "<" 399 | pvalue : 0.9711 400 | ci : [2.9959,Infinity] 401 | df : 9 402 | mean : 4.3704 403 | sd : 2.3712 404 | =========== report ========== 405 | name : "ttest(X)" 406 | h : "H0:mu>6" 407 | alpha : 0.05 408 | op : ">" 409 | pvalue : 0.0289 410 | ci : [-Infinity,5.745] 411 | df : 9 412 | mean : 4.3704 413 | sd : 2.3712 414 | =========== report ========== 415 | name : "ztest(X)" 416 | h : "H0:mu=6 when sd=2.5" 417 | alpha : 0.05 418 | op : "=" 419 | pvalue : 0.0393 420 | ci : [2.9008,5.8401] 421 | df : 10 422 | =========== report ========== 423 | name : "ttest(X,Y,mu=1,varequal=true) (pooled)" 424 | h : "H0:mu1=mu2" 425 | alpha : 0.05 426 | op : "=" 427 | pvalue : 0.4335 428 | ci : [-2.1224,2.3984] 429 | df : 18 430 | mean : "mean(x)=4.3704 mean(y)=4.2324" 431 | sd : "sd(x)=2.3712 sd(y)=2.4399" 432 | =========== report ========== 433 | name : "ttest(x,y,mu=-1,paired=true)" 434 | h : "H0:mu1=mu2" 435 | alpha : 0.05 436 | op : "=" 437 | pvalue : 0.8067 438 | ci : [-2.3389,0.0704] 439 | df : 9 440 | mean : "mean(x-y)=-1.1342" 441 | sd : "sd(x-y)=1.684" 442 | =========== report ========== 443 | name : "ttest(x,y,mu=1,varequal=false), Welch t-test" 444 | h : "H0:mu1=mu2" 445 | alpha : 0.05 446 | op : "=" 447 | pvalue : 0.4335 448 | ci : [-2.1225,2.3985] 449 | df : 17.9854 450 | mean : "mean(x)=4.3704 mean(y)=4.2324" 451 | sd : "sd(x)=2.3712 sd(y)=2.4399" 452 | =========== report ========== 453 | name : "ftest(X, Y)" 454 | h : "H0:σ1/σ2=1" 455 | alpha : 0.05 456 | op : "=" 457 | pvalue : 0.9337 458 | ci : [0.2346,3.8027] 459 | df : [9,9] 460 | ratio : 0.9445 461 | =========== report ========== 462 | name : "chisqtest(X)" 463 | h : "H0:σ1=σ" 464 | alpha : 0.05 465 | op : "=" 466 | pvalue : 0.9644 467 | ci : [1.7926,12.6278] 468 | df : 9 469 | =========== report ========== 470 | name : "binomtest({x:7,n:12,p:0.4,op:">"})" 471 | h : "H0:p>0.4" 472 | alpha : 0.05 473 | op : ">" 474 | pvalue : 0.9427 475 | ci : [0,0.819] 476 | df : 1 477 | p : 0.5833 478 | =========== report ========== 479 | name : "binomtest({x:7,n:12,p:0.4,op:"<"})" 480 | h : "H0:p<0.4" 481 | alpha : 0.05 482 | op : "<" 483 | pvalue : 0.1582 484 | ci : [0.3152,1] 485 | df : 1 486 | p : 0.5833 487 | =========== report ========== 488 | name : "binomtest({x:7,n:12,p:0.4})" 489 | h : "H0:p=0.4" 490 | alpha : 0.05 491 | op : "=" 492 | pvalue : 0.2417 493 | ci : [0.2767,0.8483] 494 | df : 1 495 | p : 0.5833 496 | =========== report ========== 497 | name : "proptest({x:91,n:100,p:0.9,correct:false}), zprop1" 498 | h : "H0:p=0.9" 499 | alpha : 0.05 500 | op : "=" 501 | pvalue : 0.7389 502 | ci : [0.8377,0.9519] 503 | df : 1 504 | p : 0.91 505 | =========== report ========== 506 | name : "proptest({x:23,n1:102,y:25,n2:135,correct:false,p:0.5}), zprop2" 507 | h : "H0:p1-p2=0" 508 | alpha : 0.05 509 | op : "=" 510 | pvalue : 0.4446 511 | ci : [-0.063,0.1436] 512 | df : 1 513 | p : [0.2255,0.1852] 514 | =========== report ========== 515 | name : "proptest({x:8,n1:100,y:12,n2:200,op:"<",correct:false,p:0.5}), zprop2 516 | " 517 | h : "H0:p1-p2<0" 518 | alpha : 0.05 519 | op : "<" 520 | pvalue : 0.2563 521 | ci : [-0.0303,Infinity] 522 | df : 1 523 | p : [0.08,0.06] 524 | ``` 525 | 526 | -------------------------------------------------------------------------------- /htm/article3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

Vis.js -- 另一個強大的 JavaScript 繪圖函式庫

41 |

雖然前述的 d3.js 與 c3.js 可以做到繪圖功能,但是這兩個函式庫強調的是互動性介面,而不是繪圖功能的部份。

42 |

於是、我找到了 vis.js 這個專注於繪圖的函式庫,這個函式庫雖然再互動性上表現得沒有 c3 那麼好,但是在繪圖功能上卻非常的完整,該有的圖型幾乎都有,特別是有關「 3D 地形圖」、「網路線圖」和的部份,是 C3 所不具備的功能,因此我們拿 vis.js 來繪製這兩類的圖形。

43 |

您可以點選下列連結,看看 vis.js 的眾多範例,相信您會對這個繪圖框架感到印象深刻的。

44 | 47 |

舉例而言、以下網頁是用來繪製 3D 地形圖的完整原始碼,

48 |

網址:http://visjs.org/examples/graph3d/example01_basis.html

49 |
50 | 圖、用 Vis.js 繪製 3D 圖形

圖、用 Vis.js 繪製 3D 圖形

51 |
52 |

以下是上述範例的完整 HTML 檔案。

53 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
 54 | <html>
 55 | <head>
 56 |   <title>Graph 3D demo</title>
 57 | 
 58 |   <style>
 59 |     body {font: 10pt arial;}
 60 |   </style>
 61 | 
 62 |   <script type="text/javascript" src="../../dist/vis.js"></script>
 63 | 
 64 |   <script type="text/javascript">
 65 |     var data = null;
 66 |     var graph = null;
 67 | 
 68 |     function custom(x, y) {
 69 |       return (Math.sin(x/50) * Math.cos(y/50) * 50 + 50);
 70 |     }
 71 | 
 72 |     // Called when the Visualization API is loaded.
 73 |     function drawVisualization() {
 74 |       // Create and populate a data table.
 75 |       data = new vis.DataSet();
 76 |       // create some nice looking data with sin/cos
 77 |       var counter = 0;
 78 |       var steps = 50;  // number of datapoints will be steps*steps
 79 |       var axisMax = 314;
 80 |       var axisStep = axisMax / steps;
 81 |       for (var x = 0; x < axisMax; x+=axisStep) {
 82 |         for (var y = 0; y < axisMax; y+=axisStep) {
 83 |           var value = custom(x,y);
 84 |           data.add({id:counter++,x:x,y:y,z:value,style:value});
 85 |         }
 86 |       }
 87 | 
 88 |       // specify options
 89 |       var options = {
 90 |         width:  '600px',
 91 |         height: '600px',
 92 |         style: 'surface',
 93 |         showPerspective: true,
 94 |         showGrid: true,
 95 |         showShadow: false,
 96 |         keepAspectRatio: true,
 97 |         verticalRatio: 0.5
 98 |       };
 99 | 
100 |       // Instantiate our graph object.
101 |       var container = document.getElementById('mygraph');
102 |       graph = new vis.Graph3d(container, data, options);
103 |     }
104 |   </script>
105 | </head>
106 | 
107 | <body onload="drawVisualization();">
108 | <div id="mygraph"></div>
109 | 
110 | <div id="info"></div>
111 | </body>
112 | </html>
113 |

而在網路圖方面,您甚至可以指定每個節點應該呈現的圖片,以下是一個繪製電腦網路圖的範例。

114 | 117 |
118 | 圖、用 vis.js 繪製電腦網路圖

圖、用 vis.js 繪製電腦網路圖

119 |
120 |

以下是上述範例的完整 HTML 檔案。

121 |
<!doctype html>
122 | <html>
123 | <head>
124 |   <title>Network | Images</title>
125 | 
126 |   <style type="text/css">
127 |     body {
128 |       font: 10pt arial;
129 |     }
130 |     #mynetwork {
131 |       width: 600px;
132 |       height: 600px;
133 |       border: 1px solid lightgray;
134 |     }
135 |   </style>
136 | 
137 |   <script type="text/javascript" src="../../dist/vis.js"></script>
138 |   <link href="../../dist/vis.css" rel="stylesheet" type="text/css" />
139 | 
140 |   <script type="text/javascript">
141 |     var nodes = null;
142 |     var edges = null;
143 |     var network = null;
144 | 
145 |     var DIR = 'img/refresh-cl/';
146 |     var LENGTH_MAIN = 150;
147 |     var LENGTH_SUB = 50;
148 | 
149 |     // Called when the Visualization API is loaded.
150 |     function draw() {
151 |       // Create a data table with nodes.
152 |       nodes = [];
153 | 
154 |       // Create a data table with links.
155 |       edges = [];
156 | 
157 |       nodes.push({id: 1, label: 'Main', image: DIR + 'Network-Pipe-icon.png', shape: 'image'});
158 |       nodes.push({id: 2, label: 'Office', image: DIR + 'Network-Pipe-icon.png', shape: 'image'});
159 |       nodes.push({id: 3, label: 'Wireless', image: DIR + 'Network-Pipe-icon.png', shape: 'image'});
160 |       edges.push({from: 1, to: 2, length: LENGTH_MAIN});
161 |       edges.push({from: 1, to: 3, length: LENGTH_MAIN});
162 | 
163 |       for (var i = 4; i <= 7; i++) {
164 |         nodes.push({id: i, label: 'Computer', image: DIR + 'Hardware-My-Computer-3-icon.png', shape: 'image'});
165 |         edges.push({from: 2, to: i, length: LENGTH_SUB});
166 |       }
167 | 
168 |       nodes.push({id: 101, label: 'Printer', image: DIR + 'Hardware-Printer-Blue-icon.png', shape: 'image'});
169 |       edges.push({from: 2, to: 101, length: LENGTH_SUB});
170 | 
171 |       nodes.push({id: 102, label: 'Laptop', image: DIR + 'Hardware-Laptop-1-icon.png', shape: 'image'});
172 |       edges.push({from: 3, to: 102, length: LENGTH_SUB});
173 | 
174 |       nodes.push({id: 103, label: 'network drive', image: DIR + 'Network-Drive-icon.png', shape: 'image'});
175 |       edges.push({from: 1, to: 103, length: LENGTH_SUB});
176 | 
177 |       nodes.push({id: 104, label: 'Internet', image: DIR + 'System-Firewall-2-icon.png', shape: 'image'});
178 |       edges.push({from: 1, to: 104, length: LENGTH_SUB});
179 | 
180 |       for (var i = 200; i <= 201; i++ ) {
181 |         nodes.push({id: i, label: 'Smartphone', image: DIR + 'Hardware-My-PDA-02-icon.png', shape: 'image'});
182 |         edges.push({from: 3, to: i, length: LENGTH_SUB});
183 |       }
184 | 
185 |       // create a network
186 |       var container = document.getElementById('mynetwork');
187 |       var data = {
188 |         nodes: nodes,
189 |         edges: edges
190 |       };
191 |       var options = {
192 |         stabilize: false   // stabilize positions before displaying
193 |       };
194 |       network = new vis.Network(container, data, options);
195 |     }
196 |   </script>
197 | </head>
198 | 
199 | <body onload="draw()">
200 | 
201 | <div id="mynetwork"></div>
202 | 
203 | </body>
204 | </html>
205 |

透過這兩個範例,相信您應該可以感覺到 vis.js 的誠意,這真的是一個相當棒的繪圖函式庫啊!

206 |

參考文獻

207 | 210 |
211 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /htm/focus4.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

R.js -- 從 jStat 延伸出的開源 JavaScript 機率統計框架

41 |

我自從開始用 R 學習機率統計之後,就覺得這樣的科學計算平台真的很棒。

42 |

但可惜的是、我現在所使用的主力語言是 JavaScript,因為 JavaScript 是瀏覽器的唯一語言,而且有了 node.js 這樣的平台之後,可以通吃客戶端與伺服端兩方的應用。

43 |

於是我想要用 JavaScript 創造出一個類似 R 的環境,並且可以在 Web 上執行,所以就創造了 jsLab 專案。

44 |

但是、為了讓 jsLab 能支援那些機率統計功能,我必須尋找用 JavaScript 語言撰寫的機率統計函式庫。

45 |

在 2012 年我就注意到了 jStat 這個支援機率模型的函式庫,當時這個函式庫還有專屬的網站,但是現在這個函式庫連網站都不見了,還好在 github 裏還有一份原始碼,網址如下:

46 | 49 |

jStat 在機率模型的部分支援還算完整,但是在統計檢定的部分就相當薄弱,雖然也支援矩陣運算等功能,但是在 JavaScript 語言上, jStat 的矩陣運算支援並不算特別好的。

50 |

因此、我們決定將 jStat 重新包裝,成為一個新的 javascript 檔案,稱為 R.js ,這是 jsLab 專案的主要程式碼之一, R.js 的網址如下。

51 | 54 |

您可以看到在 R.js 檔案裏,能夠呼叫 jStat 完成的部分,我們都盡可能的交給 jStat 來做,而 jStat 在這部份也確實做得很不錯。

55 |

檔案: R.js

56 |
...
 57 | // 均等分布
 58 | R.runif=function(n, a, b) { return R.calls(n, jStat.uniform.sample, a, b); }
 59 | R.dunif=function(x, a, b) { return jStat.uniform.pdf(x, a, b); }
 60 | R.punif=function(q, a, b) { return jStat.uniform.cdf(q, a, b); }
 61 | R.qunif=function(p, a, b) { return jStat.uniform.inv(p, a, b); }
 62 | // 常態分布
 63 | R.rnorm=function(n, mean, sd) { return R.calls(n, jStat.normal.sample, mean, sd); }
 64 | R.dnorm=function(x, mean, sd) { return jStat.normal.pdf(x, mean, sd); }
 65 | R.pnorm=function(q, mean, sd) { return jStat.normal.cdf(q, mean, sd); }
 66 | // R.qnorm=function(p, mean, sd) { return R.q2x(p, function (q) { return R.pnorm(q, mean, sd);});}
 67 | R.qnorm=function(p, mean, sd) { return jStat.normal.inv(p, mean, sd); }
 68 | // 布瓦松分布
 69 | R.rpois=function(n, l) { return R.calls(n, jStat.poisson.sample, l); }
 70 | R.dpois=function(x, l) { return jStat.poisson.pdf(x, l); }
 71 | R.ppois=function(q, l) { return jStat.poisson.cdf(q, l); }
 72 | R.qpois=function(p, l) { return jStat.poisson.inv(p, l); }
 73 | 
 74 | // F 分布
 75 | R.rf=function(n, df1, df2) { return R.calls(n, jStat.centralF.sample, df1, df2); }
 76 | R.df=function(x, df1, df2) { return jStat.centralF.pdf(x, df1, df2); }
 77 | R.pf=function(q, df1, df2) { return jStat.centralF.cdf(q, df1, df2); }
 78 | R.qf=function(p, df1, df2) { return jStat.centralF.inv(p, df1, df2); }
 79 | // T 分布
 80 | R.rt=function(n, dof) { return R.calls(n, jStat.studentt.sample, dof); }
 81 | R.dt=function(x, dof) { return jStat.studentt.pdf(x, dof); }
 82 | R.pt=function(q, dof) { return jStat.studentt.cdf(q, dof); }
 83 | R.qt=function(p, dof) { return jStat.studentt.inv(p, dof); }
 84 | ...
85 |

不過、在離散的機率分布上面,jStat 就支援的比較不好,而且沒有支援像 inv 這類的函數,於是我們就得自己來補足,以下是我們用 jStat 與自己寫的程式所合成的一些離散分布原始碼。

86 |
...
 87 | R.sample1=function(a, p) { 
 88 |   var r = Math.random();
 89 |   var u = R.repeats(1.0, a.length);
 90 |   p = R.def(p, R.normalize(u));
 91 |   var psum = 0;
 92 |   for (var i in p) {
 93 |     psum += p[i];
 94 |     if (psum > r)
 95 |       return a[i];
 96 |   }
 97 |   return null;
 98 | }
 99 | 
100 | R.sample=function(x, n, p) { return R.calls(n, R.sample1, x, p); }
101 | 
102 | // 二項分布
103 | R.rbinom=function(n, N, p) { return R.calls(n, jStat.binomial.sample, N, p); }
104 | R.dbinom=function(x, N, p) { return jStat.binomial.pdf(x, N, p); }
105 | R.pbinom=function(k, N, p) { return jStat.binomial.cdf(k, N, p); }
106 | R.qbinom=function(q, N, p) { 
107 |   for (var i=0; i<=N; i++) {
108 |     if (R.pbinom(i, N, p) > q) return i;
109 |   }
110 |   return N;
111 | }
112 | 
113 | // 負二項分布
114 | R.rnbinom=function(n, N, p) { return R.calls(n, jStat.negbin.sample, N, p); }
115 | R.dnbinom=function(x, N, p) { return jStat.negbin.pdf(x, N, p); }
116 | R.pnbinom=function(k, N, p) { return jStat.negbin.cdf(k, N, p); }
117 | // R.qnbinom=function(p, N, q) { return jStat.negbin.inv(p, N, q); }
118 | R.qnbinom=function(q, N, p) { 
119 |   for (var i=0; i<N; i++) {
120 |     if (R.pnbinom(i, N, p) > q) return i;
121 |   }
122 |   return N;
123 | }
124 | ...
125 |

另外、由於 jStat 在統計檢定方面的函數也很薄弱,所以我們撰寫了以下這個檢定的抽象函數,實作時只要補足「 q2p, o2q, h, df」等函數,就可以做出一個檢定功能了。

126 |
...
127 | R.test = function(o) { // name, D, x, mu, sd, y, alpha, op
128 |   var D      = o.D;
129 |   var x      = o.x;
130 |   var alpha  = R.opt(o, "alpha", 0.05);
131 |   o.op       = R.opt(o, "op", "=");
132 |   
133 |   var pvalue, interval;
134 |   var q1     = D.o2q(o); // 單尾檢定的 pvalue
135 |   
136 |   if (o.op === "=") {
137 |     if (q1>0.5) q1 = 1-q1; // (q1>0.5) 取右尾,否則取左尾。
138 |     pvalue= 2*q1; // 對稱情況:雙尾檢定的 p 值是單尾的兩倍。
139 |     interval = [D.q2p(alpha/2, o, "L"), D.q2p(1-alpha/2, o, "R")];
140 |   } else {
141 |     if (o.op === "<") { // 右尾檢定 H0: q < 1-alpha, 
142 |       interval = [ D.q2p(alpha, o, "L"), Infinity ]; 
143 |       pvalue = 1-q1;
144 |     }
145 |     if (o.op === ">") { // 左尾檢定 H0: q > alpha
146 |       interval=[-Infinity, D.q2p(1-alpha, o, "R")];
147 |       pvalue = q1;
148 |     }
149 |   }
150 | 
151 |   return { name: o.name,
152 |            h: D.h(o),
153 |            alpha: alpha,
154 |            op: o.op, 
155 |            pvalue: pvalue, 
156 |            ci : interval, 
157 |            df : D.df(o),
158 |            report: function() { R.report(this) }
159 |            };
160 | }
161 | ...
162 |

舉例而言,以下這個物件 t1 實作了 R.test 中所需要的函數,因此我們就可以透過「 o.D = t1; t = R.test(o); 這兩行指令呼叫 R.test 函數,完成單樣本的 t 檢定工作。

163 |
var t1 = { // 單樣本 T 檢定 t = (X-mu)/(S/sqrt(n))
164 |   h:function(o) { return "H0:mu"+o.op+o.mu; }, 
165 |   o2q:function(o) {
166 |     var x = o.x, n = x.length;
167 |     // t=(X-mu)/(sd/sqrt(n))
168 |     var t = (R.mean(x)-o.mu)/(R.sd(x)/Math.sqrt(n)); 
169 |     return R.pt(t, n-1);
170 |   },
171 |   // P(X-mu/(S/sqrt(n))<t) = q ; 信賴區間 P(T<q)
172 |   // P(mu > X-t*S/sqrt(n)) = q ; 這反而成了右尾檢定,所以左尾與右尾確實會反過來
173 |   q2p:function(q, o) {
174 |     var x = o.x, n = x.length;
175 |     return R.mean(x) + R.qt(q, n-1) * R.sd(x) / Math.sqrt(n);
176 |   },
177 |   df:function(o) { return o.x.length-1; }
178 | }
179 | ...
180 | R.ttest = function(o) { 
181 |   var t;
182 |   if (typeof o.y === "undefined") {
183 |     o.name = "ttest(X)";
184 |     o.D = t1;
185 |     t = R.test(o);
186 |     t.mean = R.mean(o.x);
187 |     t.sd   = R.sd(o.x);
188 |   } else {
189 |

目前我們已經在 R.js 中加入了大部份的機率分布、還有基本的「有母數」檢定功能,之後會再加入「無母數檢定的功能」。

190 |

另外、我們也已經加入了基本的圖表繪製功能在 G.js 當中,於是形成了 jsLab 專案的基本架構,希望之後還能找到更多更棒的 JavaScript 科學計算函式庫,讓 JavaScript 語言也能 成為科學計算的良好平台。

191 |

參考文獻

192 | 196 |
197 | 200 | 201 | 202 | -------------------------------------------------------------------------------- /htm/focus2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 28 | 29 | 30 | 31 |
32 |

程式人雜誌 -- 2014 年 11 月號 (開放公益出版品)

33 |
34 |
35 | 40 |

JsLab -- JavaScript 版的科學計算平台

41 |

雖然已經有很多科學計算軟體,像是 MatLab、 Mathematica、SPSS、SAS 等等,而且也有像 R、Octave、SciPy 等開放原始碼的科學計算軟體,但就是沒有以 JavaScript 為主的科學計算軟體。

42 |

於是我們決定要用 JavaScript 建構一個科學計算軟體,所以、JsLab 計劃就誕生了,關於 JsLab 的用法,可以參考下列的展示影片。

43 | 46 |

下圖是我們已經上傳到 github 上的 JsLab 專案之執行畫面,該程式是一個純粹用 HTML+JavaScript 建構的網頁,網址如下:

47 | 50 |

您可以連結到該網頁上直接使用該平台,雖然現在還沒有很強大,不過已經可以使用了。

51 |
52 | 圖、JsLab 的執行畫面 -- 繪製 3D 函數圖

圖、JsLab 的執行畫面 -- 繪製 3D 函數圖

53 |
54 |

在上述網頁中,我預設在編輯器裏放入了一個展示程式如下, JsLab 會執行該程式後將結果放在訊息視窗,並將繪圖部份顯示在右邊的窗框中。

55 |

檔案: curve3D.js

56 |
function f(x, y) { 
 57 |   return (Math.sin(x/50) * Math.cos(y/50) * 50 + 50); 
 58 | }
 59 | G.curve3d(f);
60 |

您可以將程式貼到該網頁的程式編輯區,然後按下執行即可得到執行結果。舉例而言、您可以貼上下列程式到編輯區。

61 |

檔案: curveT.js

62 |
G.curve(fx(dt, 3), {name:"dt(3)",  step:0.1});
 63 | G.curve("dt(x,10)",{name:"dt(10)", step:0.1});
 64 | G.curve(fx(dt, 25),{name:"dt(25)", step:0.1});
65 |

然後按下執行的 run 按鈕,就可以看到下列的曲線圖。

66 |
67 | 圖、JsLab 的執行畫面 -- 繪製 2D 曲線圖

圖、JsLab 的執行畫面 -- 繪製 2D 曲線圖

68 |
69 |

或者您也可以將下列程式貼到程式區,然後按下執行的 run 按鈕,就可以看到所繪出的散點圖。

70 |

檔案: plot1.js

71 |
Ax = R.rnorm(100, 10, 1);
 72 | Ay = R.rnorm(100, 0, 0.5);
 73 | Bx = R.rnorm(100, 0, 1);
 74 | By = R.rnorm(100, 0, 0.5);
 75 | G.plot(Ax, Ay, {name:"A"});
 76 | G.plot(Bx, By, {name:"B"});
77 |
78 | 圖、JsLab 的執行畫面 -- 隨機取樣後繪製散點圖

圖、JsLab 的執行畫面 -- 隨機取樣後繪製散點圖

79 |
80 |

當然、如果您將程式存檔在自己的電腦,那麼您也可以按下「選擇檔案」的按鈕,接著選取想要執行的檔案,就可以將程式上傳並執行,以下是我們透過上傳的方式執行 hist.js 程式的結果。

81 |

檔案: hist.js

82 |
var x = rnorm(1000, 5, 2);
 83 | G.hist(x, {name:"x", mode:"normalized"});
 84 | G.curve("dnorm(x, 5,2)", {name:"N(5,2)", step:0.2});
85 |
86 | 圖、JsLab 的執行畫面 -- 隨機取樣後繪製統計長條圖

圖、JsLab 的執行畫面 -- 隨機取樣後繪製統計長條圖

87 |
88 |

如果您並不想使用瀏覽器介面,也不需要繪製圖形,那麼您也可以採用 node.js 的命令列執行方式,直接引用 JsLab 背後的函式庫,像是 R.js 進行科學計算的動作,以下是我們在 node.js 中使用 R.js 進行隨機抽樣的一個範例。

89 |

檔案: sample.js

90 |
var U = require("../source/U");
 91 | U.use("../source/R", "R");
 92 | 
 93 | log("=======二項分布測試===========");
 94 | log("pbinom(7, 12, 0.4)="+pbinom(7, 12, 0.4)); // > pbinom(7, 12, 0.4) [1] 0.9426901
 95 | log("qbinom(0.9, 12, 0.4)="+qbinom(0.9, 12, 0.4)); // > qbinom(0.9, 12, 0.4)[1] 7
 96 | log("qbinom(0.95, 12, 0.4)="+qbinom(0.95, 12, 0.4)); // > qbinom(0.95, 12, 0.4)[1] 8
 97 | 
 98 | log("=======常態分布抽樣===========");
 99 | log("rnorm="+rnorm);
100 | log("rnorm(5, 2, 1)="+str(rnorm(5,2,1)));
101 | var y = rnorm(25, 0, 2);
102 | log("y="+str(y));
103 | 
104 | log("=======模擬丟銅板 100 次===========");
105 | log("sample([正, 反], 100)="+sample(["正", "反"], 100));
106 | 
107 | log("=======模擬擲骰子 100 次===========");
108 | log("sample([1,2,3,4,5,6], 100)="+sample([1,2,3,4,5,6], 100));
109 |

執行結果

110 |
D:\Dropbox\Public\jslab\test>node sample.js
111 | use ../source/R name=R
112 | use ../js/jstat.js name=jStat
113 | =======二項分布測試===========
114 | pbinom(7, 12, 0.4)=0.9426900787200003
115 | qbinom(0.9, 12, 0.4)=7
116 | qbinom(0.95, 12, 0.4)=8
117 | =======常態分布抽樣===========
118 | rnorm=function (n, mean, sd) { return R.calls(n, jStat.normal.sample, mean, sd);
119 |  }
120 | rnorm(5, 2, 1)=[2.0748,2.3562,3.014,3.6833,4.1393]
121 | y=[-0.3756,1.2935,-1.9635,0.5446,0.6514,2.7079,-1.2434,-4.8451,1.0937,2.5094,0.1
122 | 423,4.6915,1.3294,-1.3275,1.0153,2.5058,-2.5361,1.7784,3.908,-2.2349,0.186,-2.17
123 | 17,-1.4398,0.0423,1.2014]
124 | =======模擬丟銅板 100 次===========
125 | sample([正, 反], 100)=正,正,反,反,正,正,反,正,反,反,正,正,反,反,正,正,正,反,反,
126 | 正,反,正,反,反,反,反,正,正,正,反,反,反,正,反,正,反,反,正,反,正,正,正,反,正,反,反
127 | ,正,反,反,正,正,正,正,正,正,正,正,正,反,反,正,正,反,反,反,反,反,反,正,反,反,正,
128 | 反,正,反,反,正,反,正,反,反,反,正,正,反,反,正,正,正,正,反,正,反,反,正,正,反,反,反
129 | ,正
130 | =======模擬擲骰子 100 次===========
131 | sample([1,2,3,4,5,6], 100)=3,2,4,6,5,2,4,4,5,5,1,5,1,1,2,1,4,1,1,2,1,4,1,6,1,4,6
132 | ,5,1,4,1,6,1,1,2,6,1,5,1,3,3,1,3,4,2,5,6,4,3,5,2,4,3,1,2,1,6,3,2,4,1,2,1,4,2,6,3
133 | ,5,4,5,4,4,1,4,2,6,2,4,5,2,3,5,1,3,3,2,3,2,1,3,5,3,2,5,3,6,2,4,1,2
134 |

另外、目前我們也還持續的在增加 JsLab 函式庫的功能,像是我們正在為 R.js 加上各種統計檢定的功能,以下是採用 node.js 環境執行檢定的一些案例。

135 |

由於 jStat 函式庫並沒有支援這些統計檢定的函數,因此筆者只好自行撰寫,為了撰寫這些檢定的程式,我甚至將 R 的原始碼給翻了出來,網址如下:

136 | 139 |

以下是我們對這些檢定功能的一些測試範例,大部分的功能都有對應的 R 操作與執行結果,這樣我們就能利用 R 軟體來驗證我們所寫的檢定函數是否正確了。

140 |

檔案: rtest.js

141 |
var U = require("../source/U");
142 | U.use("../source/R", "R");
143 | 
144 | // x = rnorm(10, 5, 2)
145 | var x = [7.169890 ,2.188864 , 2.963868 ,7.790631 ,2.474261 ,7.694849 ,1.585007 ,4.087697 ,3.051643 ,4.697559];
146 | // y = rnorm(10, 4,2)
147 | var y = [4.9627295,6.0336209,-0.4610221,7.3744023,2.4804347,7.2053190,3.5558563,3.6505476,2.2200754,5.3021459];
148 | // py = x + rnorm(10, 1, 2)
149 | var py= [9.829046 ,2.491387 ,6.037504  ,5.709755 ,5.461208 ,7.345603 ,3.040538 ,4.856838 ,3.195437 ,7.079105];
150 | 
151 | log("x="+str(x));
152 | log("y="+str(y));
153 | 
154 | ttest({x:x, mu:6, alpha:0.05, op:"="}).report();
155 | 
156 | /* 
157 | > t.test(x, mu=6, alpha=0.05)
158 | 
159 |         One Sample t-test
160 | 
161 | data:  x
162 | t = -2.1732, df = 9, p-value = 0.05781
163 | alternative hypothesis: true mean is not equal to 6
164 | 95 percent confidence interval:
165 |  2.674155 6.066699
166 | sample estimates:
167 | mean of x 
168 |  4.370427 */
169 | 
170 | ttest({x:x, mu:6, alpha:0.05, op:"<"}).report();
171 | 
172 | /*
173 | > t.test(x, mu=6, alternative="greater")
174 | 
175 |         One Sample t-test
176 | 
177 | data:  x
178 | t = -2.1732, df = 9, p-value = 0.9711
179 | alternative hypothesis: true mean is greater than 6
180 | 95 percent confidence interval:
181 |  2.995873      Inf
182 | sample estimates:
183 | mean of x 
184 |  4.370427 
185 | */
186 | 
187 | ttest({x:x, mu:6, alpha:0.05, op:">"}).report();
188 | 
189 | /*
190 | > t.test(x, mu=6, alternative="less")
191 | 
192 |         One Sample t-test
193 | 
194 | data:  x
195 | t = -2.1732, df = 9, p-value = 0.02891
196 | alternative hypothesis: true mean is less than 6
197 | 95 percent confidence interval:
198 |      -Inf 5.744981
199 | sample estimates:
200 | mean of x 
201 |  4.370427 
202 | */
203 | 
204 | ztest({x:x, mu:6, sd:2.5, alpha:0.05, op:"="}).report();
205 | 
206 | ttest({x:x, y:y, mu:1, alpha:0.05, varequal:true, op:"="}).report();
207 | 
208 | /*
209 | > t.test(x, y, mu=1, conf.level=0.95, var.equal=T, alternative="two.sided");
210 | 
211 |         Two Sample t-test
212 | 
213 | data:  x and y
214 | t = -0.8012, df = 18, p-value = 0.4335
215 | alternative hypothesis: true difference in means is not equal to 1
216 | 95 percent confidence interval:
217 |  -2.122363  2.398395
218 | sample estimates:
219 | mean of x mean of y 
220 |  4.370427  4.232411 */
221 | 
222 | ttest({x:x, y:py, mu:-1, alpha:0.05, paired:true, op:"="}).report();
223 | 
224 | /*
225 | > t.test(x, py, mu=-1, conf.level=0.95, paired=T)
226 | 
227 |         Paired t-test
228 | 
229 | data:  x and py
230 | t = -0.252, df = 9, p-value = 0.8067
231 | alternative hypothesis: true difference in means is not equal to -1
232 | 95 percent confidence interval:
233 |  -2.33885689  0.07042649
234 | sample estimates:
235 | mean of the differences 
236 |               -1.134215 */
237 | 
238 | ttest({x:x, y:y, mu:1, alpha:0.05, op:"="}).report();
239 | 
240 | /*
241 | > t.test(x, y, mu=1, conf.level=0.95, alternative="two.sided");
242 | 
243 |         Welch Two Sample t-test
244 | 
245 | data:  x and y
246 | t = -0.8012, df = 17.985, p-value = 0.4335
247 | alternative hypothesis: true difference in means is not equal to 1
248 | 95 percent confidence interval:
249 |  -2.122495  2.398527
250 | sample estimates:
251 | mean of x mean of y 
252 |  4.370427  4.232411 
253 | */
254 | 
255 | ftest({x:x, y:y}).report();
256 | 
257 | /*
258 | > var.test(x,y)
259 | 
260 |         F test to compare two variances
261 | 
262 | data:  x and y
263 | F = 0.9445, num df = 9, denom df = 9, p-value = 0.9337
264 | alternative hypothesis: true ratio of variances is not equal to 1
265 | 95 percent confidence interval:
266 |  0.2346094 3.8026974
267 | sample estimates:
268 | ratio of variances 
269 |          0.9445362 
270 | */
271 | 
272 | var vx = [175, 176, 173, 175, 174, 173, 173, 176, 173, 179];
273 | vartest({x:vx, sd:2, alpha:0.05, op:"="}).report();
274 | // R 軟體沒有此函數,測試請看湯銀才 143 頁
275 | // 信賴區間 (1.793, 12.628)
276 | 
277 | binomtest({x:7, n:12, p:0.4, op:">"}).report();
278 | 
279 | /*
280 | > binom.test(x=7, n=12, p=0.4, alternative="less")
281 | 
282 |         Exact binomial test
283 | 
284 | data:  7 and 12
285 | number of successes = 7, number of trials = 12, p-value = 0.9427
286 | alternative hypothesis: true probability of success is less than 0.4
287 | 95 percent confidence interval:
288 |  0.0000000 0.8189752
289 | sample estimates:
290 | probability of success 
291 |              0.5833333 
292 | */
293 | 
294 | binomtest({x:7, n:12, p:0.4, op:"<"}).report();
295 | /*
296 | > binom.test(x=7, n=12, p=0.4, alternative="greater")
297 | 
298 |         Exact binomial test
299 | 
300 | data:  7 and 12
301 | number of successes = 7, number of trials = 12, p-value = 0.1582
302 | alternative hypothesis: true probability of success is greater than 0.4
303 | 95 percent confidence interval:
304 |  0.3152378 1.0000000
305 | sample estimates:
306 | probability of success 
307 |              0.5833333 
308 | */
309 | 
310 | 
311 | 
312 | binomtest({x:7, n:12, p:0.4}).report(); // 有誤,p-value 與 R 不同
313 | 
314 | /*
315 | > binom.test(x=7, n=12, p=0.4)
316 | 
317 |         Exact binomial test
318 | 
319 | data:  7 and 12
320 | number of successes = 7, number of trials = 12, p-value = 0.2417 ==> R.js ??? error : pvalue  : 0.1146
321 | alternative hypothesis: true probability of success is not equal to 0.4
322 | 95 percent confidence interval:
323 |  0.2766697 0.8483478
324 | sample estimates:
325 | probability of success 
326 |              0.5833333 
327 | */
328 | 
329 | 
330 | proptest({x:91, n:100, p:0.9, correct:false}).report();
331 | 
332 | /*  1-sample proportions test without continuity correction
333 | 
334 | data:  91 out of 100, null probability 0.9
335 | X-squared = 0.1111, df = 1, p-value = 0.7389
336 | alternative hypothesis: true p is not equal to 0.9
337 | 95 percent confidence interval:
338 |  0.8377379 0.9519275
339 | sample estimates:
340 |    p 
341 | 0.91 */
342 | 
343 | proptest({x:23, n1:102, y:25, n2:135, correct:false}).report();
344 | 
345 | /*
346 | > success = c(23, 25)
347 | > total = c(102, 135)
348 | > prop.test(success, total)
349 | 
350 |         2-sample test for equality of proportions with continuity correction
351 | 
352 | data:  success out of total
353 | X-squared = 0.3615, df = 1, p-value = 0.5477
354 | alternative hypothesis: two.sided
355 | 95 percent confidence interval:
356 |  -0.07256476  0.15317478
357 | sample estimates:
358 |    prop 1    prop 2 
359 | 0.2254902 0.1851852 
360 | */
361 | 
362 | proptest({x:8, n1:100, y:12, n2:200, op:"<", correct:false}).report();
363 | 
364 | /*
365 | > prop.test(c(8,12), c(100,200), alternative="greater", correct=F)
366 | 
367 |         2-sample test for equality of proportions without continuity
368 |         correction
369 | 
370 | data:  c(8, 12) out of c(100, 200)
371 | X-squared = 0.4286, df = 1, p-value = 0.2563
372 | alternative hypothesis: greater
373 | 95 percent confidence interval:
374 |  -0.03248088  1.00000000 => R.js ??? [-0.0303,Infinity]
375 | sample estimates:
376 | prop 1 prop 2 
377 |   0.08   0.06 
378 | */
379 |

執行結果

380 |
D:\Dropbox\Public\jslab\test>node rtest
381 | use ../source/R name=R
382 | use ../js/jstat.js name=jStat
383 | x=[7.1699,2.1889,2.9639,7.7906,2.4743,7.6948,1.585,4.0877,3.0516,4.6976]
384 | y=[4.9627,6.0336,-0.461,7.3744,2.4804,7.2053,3.5559,3.6505,2.2201,5.3021]
385 | =========== report ==========
386 | name    : "ttest(X)"
387 | h       : "H0:mu=6"
388 | alpha   : 0.05
389 | op      : "="
390 | pvalue  : 0.0578
391 | ci      : [2.6742,6.0667]
392 | df      : 9
393 | mean    : 4.3704
394 | sd      : 2.3712
395 | =========== report ==========
396 | name    : "ttest(X)"
397 | h       : "H0:mu<6"
398 | alpha   : 0.05
399 | op      : "<"
400 | pvalue  : 0.9711
401 | ci      : [2.9959,Infinity]
402 | df      : 9
403 | mean    : 4.3704
404 | sd      : 2.3712
405 | =========== report ==========
406 | name    : "ttest(X)"
407 | h       : "H0:mu>6"
408 | alpha   : 0.05
409 | op      : ">"
410 | pvalue  : 0.0289
411 | ci      : [-Infinity,5.745]
412 | df      : 9
413 | mean    : 4.3704
414 | sd      : 2.3712
415 | =========== report ==========
416 | name    : "ztest(X)"
417 | h       : "H0:mu=6 when sd=2.5"
418 | alpha   : 0.05
419 | op      : "="
420 | pvalue  : 0.0393
421 | ci      : [2.9008,5.8401]
422 | df      : 10
423 | =========== report ==========
424 | name    : "ttest(X,Y,mu=1,varequal=true) (pooled)"
425 | h       : "H0:mu1=mu2"
426 | alpha   : 0.05
427 | op      : "="
428 | pvalue  : 0.4335
429 | ci      : [-2.1224,2.3984]
430 | df      : 18
431 | mean    : "mean(x)=4.3704 mean(y)=4.2324"
432 | sd      : "sd(x)=2.3712 sd(y)=2.4399"
433 | =========== report ==========
434 | name    : "ttest(x,y,mu=-1,paired=true)"
435 | h       : "H0:mu1=mu2"
436 | alpha   : 0.05
437 | op      : "="
438 | pvalue  : 0.8067
439 | ci      : [-2.3389,0.0704]
440 | df      : 9
441 | mean    : "mean(x-y)=-1.1342"
442 | sd      : "sd(x-y)=1.684"
443 | =========== report ==========
444 | name    : "ttest(x,y,mu=1,varequal=false), Welch t-test"
445 | h       : "H0:mu1=mu2"
446 | alpha   : 0.05
447 | op      : "="
448 | pvalue  : 0.4335
449 | ci      : [-2.1225,2.3985]
450 | df      : 17.9854
451 | mean    : "mean(x)=4.3704 mean(y)=4.2324"
452 | sd      : "sd(x)=2.3712 sd(y)=2.4399"
453 | =========== report ==========
454 | name    : "ftest(X, Y)"
455 | h       : "H0:σ1/σ2=1"
456 | alpha   : 0.05
457 | op      : "="
458 | pvalue  : 0.9337
459 | ci      : [0.2346,3.8027]
460 | df      : [9,9]
461 | ratio   : 0.9445
462 | =========== report ==========
463 | name    : "chisqtest(X)"
464 | h       : "H0:σ1=σ"
465 | alpha   : 0.05
466 | op      : "="
467 | pvalue  : 0.9644
468 | ci      : [1.7926,12.6278]
469 | df      : 9
470 | =========== report ==========
471 | name    : "binomtest({x:7,n:12,p:0.4,op:">"})"
472 | h       : "H0:p>0.4"
473 | alpha   : 0.05
474 | op      : ">"
475 | pvalue  : 0.9427
476 | ci      : [0,0.819]
477 | df      : 1
478 | p       : 0.5833
479 | =========== report ==========
480 | name    : "binomtest({x:7,n:12,p:0.4,op:"<"})"
481 | h       : "H0:p<0.4"
482 | alpha   : 0.05
483 | op      : "<"
484 | pvalue  : 0.1582
485 | ci      : [0.3152,1]
486 | df      : 1
487 | p       : 0.5833
488 | =========== report ==========
489 | name    : "binomtest({x:7,n:12,p:0.4})"
490 | h       : "H0:p=0.4"
491 | alpha   : 0.05
492 | op      : "="
493 | pvalue  : 0.2417
494 | ci      : [0.2767,0.8483]
495 | df      : 1
496 | p       : 0.5833
497 | =========== report ==========
498 | name    : "proptest({x:91,n:100,p:0.9,correct:false}), zprop1"
499 | h       : "H0:p=0.9"
500 | alpha   : 0.05
501 | op      : "="
502 | pvalue  : 0.7389
503 | ci      : [0.8377,0.9519]
504 | df      : 1
505 | p       : 0.91
506 | =========== report ==========
507 | name    : "proptest({x:23,n1:102,y:25,n2:135,correct:false,p:0.5}), zprop2"
508 | h       : "H0:p1-p2=0"
509 | alpha   : 0.05
510 | op      : "="
511 | pvalue  : 0.4446
512 | ci      : [-0.063,0.1436]
513 | df      : 1
514 | p       : [0.2255,0.1852]
515 | =========== report ==========
516 | name    : "proptest({x:8,n1:100,y:12,n2:200,op:"<",correct:false,p:0.5}), zprop2
517 | "
518 | h       : "H0:p1-p2<0"
519 | alpha   : 0.05
520 | op      : "<"
521 | pvalue  : 0.2563
522 | ci      : [-0.0303,Infinity]
523 | df      : 1
524 | p       : [0.08,0.06]
525 |
526 | 529 | 530 | 531 | --------------------------------------------------------------------------------