數字是一切的開始......
歡迎進入到Julia的世界!我們先來試試看一些簡單的程式。
x = 5
y = 4::Int64
z = x + y
println(z)
這是一段非常簡單的程式,他做的事情是把x
跟y
相加,並且印在螢幕上。
在第一行x = 5
,這是把5
這個值指定給x
這個變數,由於Julia是個動態語言,所以我們可以不用宣告他的型別,如果要宣告型別,就會像第二行一樣讓Int64
型別綁到4
這個值上,並且把他指定給y
變數,這件事在動態語言中意義不大,除非是要指定特定型別。
以上的程式碼輸出則會是
9
小提醒:如果整數沒有宣告型別的話會自動判定成
Int64
,浮點數的話則是Float64
,在32 bit的電腦上則會是Int32
跟Float32
通常程式語言會有兩大類表示數字的型別,一種是整數 (integer),另一種是浮點數 (float)。
整數就是大家所熟知的,像是1
、0
、-1000
等等都歸類為整數,也就是不具小數點以下位數的數字。
浮點數就是含有小數點的數字,像是3.1415
、2.718281828
,但是只能表示有限小數,對於無限小數通常無法表達。
Julia跟整數相關的型別有Int128
、Int64
、Int32
、Int16
跟Int8
,Int代表integer的意思,後面的數字代表著儲存這個值用掉的記憶體空間大小。Int64
會用掉64bit的空間,以此類推。
跟浮點數相關的型別有Float64
、Float32
跟Float16
,Float代表著float的意思,後面的數字跟上面一樣是用掉的記憶體空間。
是不是很簡單呢?
由於Julia是個動態型別的語言,所以變數可以指向很多不同的值!
x = 5
println(x)
println(typeof(x))
x = 6.0
println(x)
println(typeof(x))
你會看到的結果是
5
Int64
6.0
Float64
一開始我們把x
設成5
,我們印出x
,會發現x
的型別是Int64
,當我把x
指向其他值時,x
的型別也跟著改變,這代表著在Julia中型別是跟著值的,而不是變數。
object_id()
是個好用的函數,他會給出x
所指向的值的記憶體位置,他可以幫你確認是不是同一個人囉~
我們來看一段程式碼
x = 5
println(object_id(x))
x = 6.0
println(object_id(x))
x = 5
println(object_id(x))
println(object_id(5))
在我這邊的輸出是
0x1595c9b31d160009
0x0147908c8135e7ae
0x1595c9b31d160009
0x1595c9b31d160009
你可以看到第一次跟第三次把5
這個值指定給x
,我們執行object_id(x)
的話他會去問值的記憶體位置。
兩次的記憶體位置都是一樣的,而且他不會因為途中把x
指定給其他值而改變。
在最後我們直接去問5
這個值的記憶體位置,大家會發現跟上面的是一致的。
在Julia中,值是不變的 (immutable),除非是一些集合 (collections)或是後續提到的特殊型別,不然值被創造出來之後,Julia會一直利用他,直到被"資源回收"為止。
在Julia中,數字的運算非常簡單
1 + 1 # 加法
2.0 - 1 # 減法
3.14 * 4 # 乘法
6.3 / 3 # 除法
4.5 ^ 2 # 次方
數字運算非常的直覺!
Julia在不同型別之間的數字運算非常簡單,他會自動幫你轉型喔~~~
像上面的減法是由一個Float64
跟Int64
不同型別的值做運算,他會一致轉成Float64
做運算,所以結果會是
1.0
所以乘法的結果就會是
12.56
在大家印象中的靜態型別語言,像C、C++、Java等等,需要在使用前先宣告型別、變數一旦宣告型別之後就不能改型別、不同型別的變數之間要運算需要做轉型 (cast),以上這些限制會讓大家在使用上覺得不方便。
靜態型別跟動態型別最大的差別在於型別是跟著變數還是值。
在靜態型別中,型別是跟著變數的,所以變數一旦宣告之後就只能指向同樣型別的值,不同型別的變數之間要做運算的話就要做轉型。好處是編譯器可以在compile-time就先知道變數的型別,然後做最佳化。壞處是以上講到的限制。
在動態型別中,型別是跟著值的,所以變數可以指向不同型別的值,看起來就很動態,這是好處之一,但是壞處就是編譯器無法在compile-time就知道變數的型別,所以不能做最佳化,只能放在runtime做。