# Julia 進階教學 {%hackmd @themes/orangeheart %} ###### tags: `Numerical Methods` 在上一篇[Julia 基礎教學](https://hackmd.io/@yueswater/Julia_Basic)中,我們學習了最基礎的數學運算、設計函式以及安裝套件。而本篇文章將會針對 $\texttt{Julia}$ 中的型別、資料結構進行說明,並著重在迴圈與流程控制。小提醒,如果沒有看過上一篇文章的要記得去看唷! ## 型別(type) 所謂型別,可以把它想像成血型:不同的血型都有不同的抗原與抗體。一般而言,一個程式語言的型別大致上可以分為以下幾種: - 整數(integer) - 浮點數(float) - 字元(character) - 字串(string) - 布林值(boolen) 如果我們好奇一個變數的型別是什麼,可以使用 `typeof()` 來檢查或加以確認。以下就將上述這些型別分門別類,一一介紹吧。 ### 整數與浮點數 數學可以說是程式語言最好的夥伴,無論我們的目的是什麼,到頭來還是要與數字打交道。舉例來說,要寫一個迴圈總要告訴系統我們要從什麼數字開始、什麼數字結束;又或者我們想要進行索引,那麼應該用 $1$ 進行索引呢?還是用 $1.0$?這些問題都圍繞著一個核心:我們該怎麼樣看數字。首先我們要知道,在現實世界理解的數字跟電腦所使用的數字有所不同。由於電腦是透過 $0$ 和 $1$ (即二進位)的方式儲存資料,因此儘管 $1$ 和 $1.0$ 在我們眼中看起來是一樣的,但在電腦的眼裡,**它們就是不一樣!** #### 走一步是一步:整數 在電腦科學中,整數的概念指數學上整數的一個有限子集。[^1] 用簡單的話來說,每當我們要往前走,跨出一步那就真的是一步,意思是不會有「半步」這種情形發生。我們常見的 $1, 2, 3, 4, \cdots$ 都是整數。而在 $\texttt{Julia}$ 裡頭,整數的位元數、最大、最小值如下表所示: | Type | 位元數 | 最小值 | 最大值 | | :-: | :-: | :-: | :-: | | `Int8`| 8 | $-2^7$ | $2^7 - 1$ | | `Int16`| 16 | $-2^{15}$ | $2^{15} - 1$ | | `Int32`| 32 | $-2^{31}$ | $2^{31} - 1$ | | `Int64`| 64 | $-2^{63}$ | $2^{63} - 1$ | | `Int128`| 128 | $-2^{127}$ | $2^{127} - 1$ | 那整數型別要怎麼用運用呢?我們來參考一下 111學年度學測數 B 單選第一題: :::warning 試問有多少個整數 $x$ 滿足 $2|x| + x < 10$? ::: 其實這題的一個作法是:利用迴圈(之後的小節會提到,不用擔心)從某個整數型別的最小值一直跑到最大值,如果符合上述不等式就在計數器加 $1$。範例程式碼如下:[^2] ```julia number = 0 for i in typemin(Int8) - 1:typemax(Int8) if 2 * abs(i) + i < 10 number += 1 end end print(number) ## 13 ``` ### 走一步有半步:浮點數 不同於整數型別,浮點指的是帶有小數的數值,比如 $1.2, 3.4, 5.6 \cdots$。根據 IEEE 754 的規定,浮點數的呈現方式如下: $$ \texttt{Value} = \texttt{sign} \times \texttt {exponent} \times \texttt {fraction} $$ 也就是浮點數的實際值,等於符號位(sign bit)乘以指數偏移值(exponent bias)再乘以分數值(fraction)。[^3] 而根據不同的符號位、指數偏移值與分數值,則分為半精度、單精度與雙精度浮點數。不過這篇文章不是專門談論資料結構的,因此就不贅述它們之間的差別。而 $\texttt{Julia}$ 中浮點數的位元數、最大、最小值如下表所示: | 型別 | 精度 | 位元數 | |:-------:|:---------:|:--------------:| | `Float16` | 半精度 | 16 | | `Float32` | 單精度 | 32 | | `Float64` | 雙精度 | 64 | 我們一樣參考學測考題,來看看如何應用浮點數吧!111學年度學測數 A 選填第十三題: :::warning 有一款線上遊戲推出「十連抽」的抽卡機制,「十連抽」意思為系統自動做十次的抽卡 動作。若每次「十連抽」需用 $1500$ 枚代幣,抽中金卡的機率在前九次皆為 $2\%$,在第 十次為 $10\%$。今某生有代幣 $23000$ 枚,且不斷使用「十連抽」,抽到不能再抽為止。則某生抽到金卡張數的期望值為多少張? ::: 如果有學過統計學的讀者可以很快地看出,這題的隨機變數服從二項分配,因此可以寫成 $$ X \sim \operatorname{B}(n, p) $$ 而它的期望值是 $\mathbb{E}(X) = np$。因此十連抽中,前九次抽到金卡與第十次抽到金卡的期望值為: $$ 9\times 2\%+ 1\times 10\% = 0.28 $$ 而 $23000$ 枚代幣可抽 $\lfloor {23000\over 1500}\rfloor = 15$次。[^4] 因此,程式碼可以寫成: ```julia E_tenspins = 9 * 0.02 + 1 * 0.1 #「一次」十連抽的期望值 spin_times = Int64(round(23000 / 1500)) #共可抽幾次 answer = E_tenspins * spin_times ## 4.2 ``` ### 字元與字串 在電腦語言中,[ASCII code](https://zh.wikipedia.org/wiki/ASCII)是最常見的文字編碼系統之一。如果我們輸入一個字元,系統就會回傳它的 ASCII code 與 Unicode: ```=julia c = 'x' ## 'x': ASCII/Unicode U+0078 (category Ll: Letter, lowercase) ``` 而 ### 布林值 ## 資料結構(data structure) ## 迴圈(loop) ## 流程控制(control flow) [^1]:參考自[維基百科──整數(電腦科學)](https://zh.wikipedia.org/wiki/%E6%95%B4%E6%95%B0_(%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A7%91%E5%AD%A6)) [^2]:但是我個人認為這種寫法不是最好的,畢竟我要老實承認,當初在寫這題的時候我是從 `Int128` 開始嘗試,但它的最大值與最小值都快到遙遠的地方了,程式碼大概運行了 $10$ 分鐘都沒有跑完,所以我一個個嘗試,從 `Int64` 一直換到 `Int8`,才算快了一點。如果有讀者有更好的想法,歡迎告訴我!我會很感激你的 :cry: [^3]:參考自[維基百科──IEEE 754](https://zh.wikipedia.org/wiki/IEEE_754) [^4]:參考自[朱氏幸福:111年大學學測-數學A詳解](https://chu246.blogspot.com/2022/01/111-a.html)