tags |
---|
Golang魔法使 |
昨天小櫻戰鬥的事被好友「大道寺知世」用 V8 偷拍的一清二礎,你在偷偷搜集 Golang 牌的事,已經被發現了,知世也想要變強,他想要得到石鬼面變成不死之身 如今只能把知世加入戰隊一起奮鬥了
以「電腦科學」的角度來出發,電腦是怎麼表達數字的,大家都知道魔仗(電腦)內部是由 0 和 1 來運作的,那怎麼表示整數呢?
- 0 0 0 0 0 0 0 0
- 0 0 0 0 0 0 0 1
- 0 0 0 0 0 0 1 0
- 0 0 0 0 0 0 1 1
- 0 0 0 0 0 1 0 0
- ...
其中一個存取 0 或 1 的單元我們稱作「位元」(bit),而每個例子中都有 8bits,根據高一下數學課教的排列組合計數原理,這 8bits,一共可以有 256 排列
10000000 (-128)
10000001 (-127)
10000010 (-126)
...
11111111 (-1)
00000000 (0)
00000001 (1)
00000010 (2)
...
01111110 (126)
01111111 (127)
在 Golang 牌中我們稱這個叫
int8
,可以用來表示(-128~127)
我們有時並不會用到負號,這時我們記作 uint8
可以表示(0~255)
00000000 (0)
00000001 (1)
00000010 (2)
...
10000000 (128)
10000001 (129)
...
11111111 (255)
uint
只能是正數,int
可以有負數int 表示負數的存法在電腦科學中稱為「二補數」
其中
int
即為英文的integer
而uint
則為unsigned integer
表示是「無符號的」整數,可能有點難記為什麼不乾脆用i8
和u8
呢?這問題很好,Rust 就是這麼認為的,因此 Rust 採用i8
,u8
來表示
package main
import "fmt"
func main(){
var num int8
num = 127
fmt.Print(num)
}
執行結果: 127
首先我們先來看第 4 行 var num int8
,var
是宣告變數的起手示,全稱為 variable,什麼是宣告變數呢?就是告訴編譯器,我需要使用一個變數叫作 num
而他是一個 int8
的型態
而這個num
的名字由各位魔法使自己決定,變數名稱由數字、英文字母及下劃線組合而成,其中要注意不可以用數字當變數名稱開頭
,相信資深工具人一定覺得理所當然,另外,並不是所有單字的可以當變數,有些名字是不能當成變數名稱的,比如若用var
當變數名稱,想就知道會出事吧?
而第 5 行 num = 127
則是告訴編譯器 num 是 127。請注意,這裡的等號是一種給予的表現,並不是數學上的等於,給予的方向是左邊接收右邊給予
第 6 行 fmt.Print(num)
則是告訴魔仗要他印出 num,若改使用 fmt.Println(num)
則魔仗則會在印出 num 後再印出換行符號(ln 代表 line) 很多語言也有採類似用法如 java, rust
然而 int8
實在是太短了,如果不小心給到 128 魔仗還會當場給我噴錯,氣氣氣氣氣,這種情況我們稱為 overflow 又稱為溢位
關於溢位
Golang牌在整數上一共給了以下這些型態
int8, uint8 int16, uint16 int32, uint32 int64, uint64 int , uint (大部分情況視為 int64, uint64)
另外大家可能會發現怎麼都是 8 的倍數,因為電腦會以 8 個 bits 做操作,所以又稱 8bits 為 1byte (1個位元組)
然而,每次都要打 var ooo int
ooo = xxx
時在太麻煩了所以又出現了幾種簡單的打法
package main
import "fmt"
func main(){
var num1 int = 10
num2 := 20
fmt.Println(num1)
fmt.Println(num2)
}
執行結果: 10 20
其中要注第5行 num2
所採用的方法是由魔仗自行判定型態,在這裡會直接把 num2
視為 int
注意,若使用
fmt.Print()
則會印出 1020 因為魔仗在用fmt.Print()
時不會自動在10後面換一行
你一定會很好奇魔仗要怎麼處理小數,現在的魔法基本上都是按照 IEEE754 來處理浮點數的,這部分比較複雜,簡單來說就是將一串浮點數拆成科學記號來表示,當然實際上沒有那麼簡單所以在此就不細講了。我們只要知道怎麼用就行了,在 Golang 中一共有兩種小數的宣告方法,分別為
- float32
- float64
因為對電腦來說,考慮到效能,無法完美處理小數,所以有兩種提供選擇。其中float64
花了2倍的空間所以存的比 float32
還要精準,通常我們會稱 float64
為雙精度浮點數
雙精度符點數 補充:有些語言會以 float 代表 float32, double 代表 float64,但是如果是採用 32, 64 這種表示法,就可以很清礎的了解該變數到底占用了多少空間,而且少背一個單字,真的很不錯
通常加減乘除是一定要有的,我們以整數來舉例
package main
import "fmt"
func main(){
n := 10
m := 20
fmt.Println(n + m)
fmt.Println(n - m)
fmt.Println(n * m)
fmt.Println(m / n)
fmt.Println(n / m)
}
執行結果 30 -10 200 2 0
在絕大多數的語言中,整數對整數運算出來的都是整數,即使是除法也不例外,n / m
是 10/20
在數學中應為 0.5
但在電腦科學中,會直接當作 0
那麼如果有負數呢?比如 -3/2 = -1.5
會變 -2
還是 -1
呢?其實不用像數學什麼 高斯符號 那麼麻煩,只要把小數位去掉就行了,所以會是 -1
package main
import "fmt"
func main(){
fmt.Println(-3/2)
}
執行結果 -1
另外,在電腦科學中,有一種計算方式叫作「取餘數」,用「%」當做記號,這裡的「%」跟一般數學、物理、化學在用的「百分比」不一樣,他是一種「取餘數的」計算方式,舉個例子:
30 % 2 會是 0 因為 30/2 = 15...0 29 % 3 會是 2 因為 29/3 = 9...2 23 % 5 會是 3 因為 23/5 = 4...3
package main
import "fmt"
func main(){
fmt.Println(30 % 2)
fmt.Println(29 % 3)
fmt.Println(23 % 5)
}
執行結果 0 2 3
如果是有負數的情況倒是比較少見,但也一樣試用
package main
import "fmt"
func main(){
fmt.Println(-24 % 7)
fmt.Println(24 % -7)
fmt.Println(-24 % -7)
}
執行結果 -3 3 -3
-24 / 7 = -3...-3 (照理說應該也可以 -4...4) 24 / -7 = -3...3 (照理說應該也可以 -4...-4) -24 / -7 = 3...-3 (照理說應該也可以 4...4)
經過以上觀察,能發現規律,當有負號參與時,取餘的值的正負號會等於被除數,也就是 %
的左側為正則出來的值也為正或零,%
左側為負則出來的值為負或零
在幾乎所有的語言中,都遵守先乘除後加減的四則運算,當你不確定運算優先序時 ()
就直接給他加下去就對了
浮點數的運算基本上和整數差不多,但要注意一下,浮點數可以和直接整數(單純數字) 做運算,但不能和 整數變數(英文) 做運算。因為和純數字時Golang魔仗會直接幫你轉成浮點數。另一方面在Golang中取餘並不適用於浮點數。
package main
import "fmt"
func main(){
m := 2.5
m = m / 2
fmt.Println(m)
}
執行結果 1.25
package main
import "fmt"
func main(){
m := 2.5
n := 2
m = m / n
fmt.Println(m)
}
那麼如果我真的這麼想要計算要怎麼辦?那麼就轉換型別吧!把浮點數轉成整數,或著把整數轉成浮點數
如果想把 int
轉成 float64
那麼就在要轉換的變數外加上 float64()
就可以了
package main
import "fmt"
func main(){
m := 2.5
n := 2
m = m / float64(n)
fmt.Println(m)
}
執行結果 1.25
這樣一來被套上 float64()
的 n 就會以 float64
的型態跟 m 做計算,要注意的事 n 仍然是 int
只有在套上時會變 float64()
,也就是說「在宣告變數後」該變數只能就是這個型態了,型態並不能轉變。(有些語言並不這麼認為,比如php, javascript)
幾乎所有的語言都有註解功能,加上註解,能幫助後續的維護,註解有相關的格式,但這邊先不做討論
在Golang牌中,用兩條斜線//
來寫單行註解 ,//
後到換行前的所有字都會被忽略
package main
import "fmt"
func main(){
m := 2.5 // m is float64
n := 2 // f is int
m = m / float64(n)
fmt.Println(m)
}
如果要寫能換行的註解則是將你的註解包在 /*
與 */
中
package main
import "fmt"
func main(){
/*
這是一個
可以跨行
的註解
*/
m := 2.5
n := 2
m = m / float64(n)
fmt.Println(m)
}
大部份的語言都是採用
//
搭配/**/
的型式 python 因為把//
拿去當做整數除法使用,所以是用#
來做註解 Coffeescript 也是是#
來做註解NASM
則是以;
來當做註解
- 學習Golang牌中整數與浮點數的宣告及運算
- 了解 uint 與 int 差別
- 整數與浮點數間型別轉換
- 變數的內容值可以變,但是型態不能變
- 註解的使用
如果是有讀過高中的朋友應該還記得什麼是複數吧!什麼?不記得了,標題就說文組不好說了,一般我們所使用的都是實數域的數,如果實數搭配虛數使用則稱複數,一般會用 a+bi
表示, a
為實部 b
為虛部,在Golang中用complex64
或complex128
來表示, 64
指的是 float32
的實部加上 float32
的虛部, 128
指的是 float64
的實部加上 float64
的虛部
package main
import "fmt"
func main(){
var m complex64 = 1 + 2i
var n complex64 = 3 + 4i
var k complex128 = 5 + 10i
fmt.Println(m + n)
// fmt.Println(m + k) 報錯(型態不同)
fmt.Println(k)
}
執行結果: (4+6i) (5+10i)
圖片來源(Go官網):The Go Programming Language Specification
這些字用來保持Golang牌的運作,不能當變數名稱
看來 2020 那時寫的幹話有點多,所以 2021 更新又刪減了一些
本文大多數圖片來自:庫洛魔法使第一季第二集