Golang——多种运算符及优先级
運(yùn)算符:
- 很久以前,流傳程序=算法+數(shù)據(jù)這樣的說法。
- 算法是什么?通俗點(diǎn)說就是解決問題的過程。小到加法指令,大到成千上萬臺(tái)服務(wù)器組成的分布式計(jì)算集群。拋去抽象概念和宏觀架構(gòu),最終都由最基礎(chǔ)的機(jī)器指令過程去處理不同層次存儲(chǔ)設(shè)備里的數(shù)據(jù)。學(xué)習(xí)語言和設(shè)計(jì)架構(gòu)不同,我們所關(guān)心的就是微觀層次,諸如語法規(guī)則所映射的機(jī)器指令, 以及數(shù)據(jù)存儲(chǔ)位置和格式等等。其中,運(yùn)算符和表達(dá)式用來串聯(lián)數(shù)據(jù)和指令,算是最基礎(chǔ) 的算法。
- 另有一句話:硬件的方向是物理,軟件的結(jié)局是數(shù)學(xué)
全部運(yùn)算符列表:
+ & += &= && == != ( ) - | -= |= || < <= [ ] * ^ *= ^= <- > >= { } / << /= <<= ++ = := , ; % >> %= >>= -- ! ... . :&^ &^=一元運(yùn)算符優(yōu)先級(jí)最高,二元?jiǎng)t分成五個(gè)級(jí)別,從高往低分別是:
- 相同優(yōu)先級(jí)的二元運(yùn)算符,從左往右依次計(jì)算
- 一元運(yùn)算符:運(yùn)算中只有1個(gè)操作數(shù)參與,如:i++,i–
- 二元運(yùn)算符:運(yùn)算中只有2個(gè)操作數(shù)參與,如:+ - * / % a+b
沒有乘冪和絕對(duì)值運(yùn)算符,對(duì)應(yīng)的是標(biāo)準(zhǔn)庫math里的Pow、Abs函數(shù)實(shí)現(xiàn)。
二元運(yùn)算符:
操作數(shù)類型必須相同,除非是無顯式類型聲明的常量,且該常量操作數(shù)會(huì)自動(dòng)轉(zhuǎn)換為另一 操作數(shù)類型。當(dāng)然,位移操作會(huì)有些不同
func main() {const i = 1 // 無顯式類型聲明的常量var j byte = 10b := i + j // v自動(dòng)轉(zhuǎn)換為byte/uint8類型。fmt.Printf("%T, %v\n", b, b)const x float32 = 1.1d := x + i // v自動(dòng)轉(zhuǎn)換為float32類型。fmt.Printf("%T, %v\n", d, d) }打印結(jié)果:
uint8, 11 float32, 2.1位移右操作數(shù)必須是無符號(hào)整數(shù),或可以轉(zhuǎn)換的無顯式類型常量
func main() {i := 1 // i是有符號(hào)int類型。j := 2 << i // 無效操作:2 << i (2 << i 已評(píng)估但未使用)fmt.PrintLn(j) }如果是非常量位移表達(dá)式,那么會(huì)優(yōu)先將無顯式類型的常量左操作數(shù)轉(zhuǎn)型
func main() {var i uint = 3j := 1.0 << 3 //常量表達(dá)式(包括常量展開)。fmt.Printf("%T,%v\n", j, j) // int, 8x := 1.0 << i // 無效操作:1 << i (shift of type float64)fmt.Printf("%T, %v\n", x, x) // 因?yàn)閤沒有提供類型,那么編譯器通過1.0推斷,顯然無法對(duì)浮點(diǎn)數(shù)做位移操作。var y int32 = 1.0 << i //自動(dòng)將1.0轉(zhuǎn)換為int32類型。fmt.Printf("%T, %v\n", y, y) // int32, 8 }位運(yùn)算符:
二進(jìn)制位運(yùn)算符比較特別的就是bit clear,在其他語言里很少見到
AND 按位與:都為1 a & b 0101 & 0011 = 0001 OR 按位或:至少一個(gè)1 a | b 0101 | 0011 = 0111 XOR 按位亦或:只有一個(gè)1 a ^ b 0101 ^ 0011 = 0110 NOT 按位取反(一元) ^a ^0111 = 1000 AND 按位清除(bit clear) a &^ b 0110 &^ 1011 = 0100 LEFT SHIFT 位左移 a << 2 0001 << 3 = 1000 RIGHT SHIFT 位右移 a >> 2 1010 >> 2 = 0010位清除(and NOT)和位亦或(XOR)是不同的。它的右操作數(shù)作用類似位圖,將有標(biāo)記的左操作數(shù)對(duì)應(yīng)二進(jìn)制位重置為0,以達(dá)到一次清除多個(gè)標(biāo)記位的目的
const (read2 byte = 1 << iotawriteexecfreeze )func main() {a := read2 | write | freezeb := read2 | freeze | execc := a &^ b // 相當(dāng)于a^ read ^ freeze,但不能包括execfmt.Printf("%04b &^ %04b = %04b\n", a, b, c) }打印結(jié)果:
1011 &^ 1101 = 0010算術(shù)運(yùn)算符:
+:加
-:減
*:乘
/:除,取結(jié)果的商
%:取余,取結(jié)果的余數(shù)
整數(shù)操作只能得到整數(shù),要想得到小數(shù),必須有浮點(diǎn)數(shù)參與運(yùn)算。/和%運(yùn)算除數(shù)不能為0
演示:
func test2() {a := 1b := 2c := 0fmt.Println("a + b = ", a+b) //3fmt.Println("a - b = ", a-b) //-1fmt.Println("a * b = ", a*b) //2fmt.Println("a / b = ", a/b) //0fmt.Println("a % b = ", a%b) //1fmt.Println("a / c = ", a/c) //panic: runtime error: integer divide by zerofmt.Println("a % c = ", a%c) //panic: runtime error: integer divide by zero }字符+
兩邊都是數(shù)值時(shí),+號(hào)是做加法運(yùn)算,兩邊都是字符串時(shí)是做字符串拼接
char類型參與算術(shù)運(yùn)算,使用的是計(jì)算機(jī)底層對(duì)應(yīng)的十進(jìn)制數(shù)值。
‘a(chǎn)’ --------- 97 a-z是連續(xù)的,'b’對(duì)應(yīng)的值是98,'c’是99
‘A’ --------- 65 A-Z是連續(xù)的,'B’對(duì)應(yīng)的值是66,'C’是67
‘0’ --------- 48 0-9是連續(xù)的,'1’對(duì)應(yīng)的值是49,'2’是50
自增自減運(yùn)算:
自增、自減運(yùn)算符只能作為獨(dú)立語句,不能用于表達(dá)式。
表達(dá)式通常是求值代碼,可作為右值或參數(shù)使用。表達(dá)式可作為語句用,但語句卻不能當(dāng)做表達(dá)式。
| ++ | 自增 | 變量的值加1 |
| - - | 自減 | 變量的值減1 |
++和-- 只能放在變量的后面使用,不支持放在前面
參與操作的時(shí)候,如果放在變量的后邊,先拿變量參與操作,后拿變量做++或者–。
最常見的用法:單獨(dú)使用。
賦值運(yùn)算符:
作用:將一個(gè)表達(dá)式的值賦給左邊,左邊必須是可修改的,不能是常量。賦值運(yùn)算符隱含了強(qiáng)制類型轉(zhuǎn)換。
| = | 普通賦值 | a=10,將10賦值給變量a |
| += | 加后賦值 | a+=b,將a+b的值給a |
| -= | 減后賦值 | a-=b,將a-b的值給a |
| *= | 乘后賦值 | a*=b,將a×b的值給a |
| /= | 除后賦值 | a/=b,將a÷b的商給a |
| %= | 取余后賦值 | a%=b,將a÷b的余數(shù)給a |
賦值運(yùn)算符和算術(shù)運(yùn)算符一起使用的時(shí)候,會(huì)優(yōu)先計(jì)算算術(shù)運(yùn)算符
var sum = 100sum += 5 //105sum /= 5 + 5 // sum = sum /(5=5)println(sum)關(guān)系運(yùn)算符:
| == | a==b,判斷a和b的值是否相等,成立為true,不成立為false |
| != | a!=b,判斷a和b的值是否不相等,成立為true,不成立為false |
| > | a>b,判斷a是否大于b,成立為true,不成立為false |
| >= | a>=b,判斷a是否大于等于b,成立為true,不成立為false |
| < | a<b,判斷a是否小于b,成立為true,不成立為false |
| <= | a<=b,判斷a是否小于等于b,成立為true,不成立為false |
關(guān)系運(yùn)算符的結(jié)果都是boolean類型,要么是true,要么是false。
不要把==寫成=,==是判斷是否相等,=是賦值
關(guān)系運(yùn)算符和算術(shù)運(yùn)算符、賦值運(yùn)算符一起運(yùn)算時(shí)的優(yōu)先級(jí)是
算術(shù)運(yùn)算符 > 關(guān)系運(yùn)算符 > 賦值運(yùn)算符
func test8() {num1 := 1num2 := 2sum := num1+3 > num2 // 先計(jì)算num1+3,再拿num1+3的結(jié)果和num2比較,最后賦值給sumfmt.Println("num1 == num2", num1 == num2) //falsefmt.Println("num1 != num2", num1 != num2) //truefmt.Println("num1 > num2", num1 > num2) //falsefmt.Println("num1 >= num2", num1 >= num2) //falsefmt.Println("num1 < num2", num1 < num2) //truefmt.Println("num1 <= num2", num1 <= num2) //truefmt.Println("sum = ", sum) //true }邏輯運(yùn)算符:
邏輯運(yùn)算符把各個(gè)運(yùn)算的關(guān)系表達(dá)式連接起來組成一個(gè)復(fù)雜的邏輯表達(dá)式,以判斷程序中的表達(dá)式是否成立,判斷的結(jié)果是 true 或 false。
在邏輯與運(yùn)算中,只要有一個(gè)表達(dá)式的值為false,那么結(jié)果就可以判定為false了,沒有必要將所有表達(dá)式的值都計(jì)算出來,短路與操作就有這樣的效果,可以提高效率。同理在邏輯或運(yùn)算中,一旦發(fā)現(xiàn)值為true,右邊的表達(dá)式將不再參與運(yùn)算。
- 短路與&&,如果左邊為真,右邊執(zhí)行;如果左邊為假,右邊不執(zhí)行。
- 短路或||,如果左邊為假,右邊執(zhí)行;如果左邊為真,右邊不執(zhí)行。
| ! | 邏輯非 | !a,結(jié)果和a的結(jié)果正好相反 |
| && | 短路與 | 作用和&相同,但是有短路效果 |
| || | 短路或 | 作用和|相同,但是有短路效果 |
運(yùn)算符優(yōu)先級(jí):
優(yōu)先級(jí)按照先后順序排序
| () | .().函數(shù)名用的 |
| ! 單目運(yùn)算符 | 邏輯非 |
| &單目運(yùn)算符 | 取地址用的 |
| */%雙目運(yùn)算符 | 算術(shù)運(yùn)算 |
| +-雙目運(yùn)算符 | 算術(shù)運(yùn)算 |
| &&雙目運(yùn)算符 | 邏輯運(yùn)算 |
| ||雙目運(yùn)算符 | 邏輯運(yùn)算 |
| =、+=、-=、*=、/=雙目運(yùn)算符 | 賦值運(yùn)算 |
總結(jié)
以上是生活随笔為你收集整理的Golang——多种运算符及优先级的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 认识API
- 下一篇: java中抓阄_如何进行抓阄