Swift 語言的基本運算子
運算子(operator)是用於檢查、更改或組合值的特殊符號或短語。例如,加法運算子(+
)求兩個數字的加和(用例 let i = 1 + 2
)。更復雜的例子包括邏輯與(logical AND)運算子 &&
(用例 if 已輸入門禁密碼 && 已通過視網膜掃描
) 以及自增運算子 ++i
,後者是將 i
儲存的值加上 1
的便捷寫法。
Swift 支援標準 C 的大多數運算子,並改進了部分行為特性,以避免常見的編碼錯誤。賦值運算子(=
)不會返回值,這樣可避免在打算使用等於運算子(==
)的地方誤用前者。算術運算子(+
、-
、*
、/
、%
等)會偵測並阻止值溢位,可避免處理超出可儲存值域範圍的數時出現意料之外的結果。如果需要支援溢位,可以選用 Swift 的溢位運算子,詳見 溢位運算子。
與 C 語言不同,Swift 允許對浮點數求餘(%
)。Swift 還提供了兩種 C 語言沒有的區間運算子(a..b
與 a...b
),作為表達值域範圍的便捷寫法。
本章講解 Swift 中的常用運算子。高階運算子 一章涉及了 Swift 的高階運算子,並講解了如何自定義運算子,以及讓標準運算子支援自定義型別的運算。
運算子相關的術語
運算子分為一元、二元以及三元運算子:
一元運算子(unary operator)對單個目標進行運算(如
-a
)。一元字首運算子(unary prefix operator)置於運算目標之前(如!b
),而一元后綴運算子(unary postfix operator)緊跟目標之後(如i++
)。二元運算子(binary operator)對兩個目標進行運算(如
2 + 3
),它們屬於中綴(infix)運算子,因為出現在運算對應的兩個目標之間。三元運算子(ternary operator)對三個目標進行運算。與 C 語言一樣,Swift 只有一個三元運算子:三元條件運算子(即
a ? b : c
)。
運算子操作的值稱為運算數(operands)。在表示式 1 + 2
中,+
符號是二元運算子,它的兩個運算數為值 1
與值 2
。
賦值運算子
賦值運算子(assignment operator,a = b
)用 b
的值初始化或更新 a
的值:
let b = 10
var a = 5
a = b
// a 的值現在等於 10
如果賦值語句的右側是包含多個值的元組,其元素可一次性提取為多個常量或變數:
let (x, y) = (1, 2)
// x 等於 1,y 等於 2
與 C / Objective-C 語言的賦值運算子不同,Swift 語言的運算子本身不會返回值。因此下面的語句不正確:
if x = y {
// 語句無效,因為“x = y”不會返回值
}
該特性可避免在希望使用等於運算子(==
)的地方誤用賦值運算子(=
)。通過不承認 if x = y
的有效性,Swift 將幫助你避免程式碼中出現這樣的錯誤。
算術運算子
Swift 支援對所有數字型別使用四種標準的算術運算子(arithmetic operator):
- 加法(
+
) - 減法(
-
) - 乘法(
*
) 除法(
/
)1 + 2 // 等於 3
5 - 3 // 等於 2
2 * 3 // 等於 6
10.0 / 2.5 // 等於 4.0
與 C / Objective-C 語言的算術運算子不同,Swift 的算術運算子預設不允許值溢位。若要支援溢位特性,可以使用 Swift 的溢位運算子(如 a &+ b
)。參見 溢位運算子。
加法運算子還支援 String
連線:
"hello, " + "world" // 等於 "hello, world"
可以將兩個 Character
值相加,或將一個 Character
值與一個 String
值相加,得到新的 String
值:
let 汪: Character = "?"
let 哞: Character = "?"
let 汪哞 = 汪 + 哞
// 汪哞 等於 "??"
參見 字串及字元的連線。
求餘運算子
求餘運算子(remainder operator,a % b
)求出) a
能裝得下多少個整數的 b
,並返回剩餘的空間大小(即整除後的餘數 remainder)。
注:求餘運算子(
%
)在其他語言中也稱作求模運算子(modulo operator)。但對負數的運算結果顯示,Swift 語言的實現是嚴格的求餘操作,而非求模操作。
求餘運算子的原理如下。
要計算 9 % 4
,首先要求出 9
裡面能裝得下多少個 4
:
如圖顯示,9
裡面能裝得下兩個 4
,因此餘數為 1
(橙色部分)。
Swift 語言的寫法為:
9 % 4 // 等於 1
要求出 a % b
的結果,%
運算子會計算下面的式子,並將 餘數
作為輸出結果返回:
a
= (b
× 某個乘數
) + 餘數
其中 某個乘數
是 a
中能裝下 b
的最大數目。
將 9
與 4
代入等式,可求得:
9
= (4
× 2
) + 1
a
為負值時,求餘數的方法不變:
-9 % 4 // 等於 -1
將 -9
與 4
代入等式,可求得:
-9
= (4
× -2
) + -1
得到的餘數值為 -1
。
b
為負值時,b
的符號將被忽略。因此 a % b
與 a % -b
將總得到相同的結果。
浮點數的餘數計算
與 C / Objective-C 的餘數運算子不同,Swift 的餘數運算子還能對浮點數進行計算:
8 % 2.5 // 等於 0.5
上例中,8
除以 2.5
等於 3
,餘數為 0.5
,因此餘數運算子返回 Double
值 0.5
。
自增與自減運算子
與 C 語言類似,Swift 也提供了自增運算子(increment operator,++
)與自減運算子(decrement operator,--
),作為將數字變數的值加上或減去 1
的便捷寫法。這兩個運算子可以對任何整型或浮點型的變數使用。
var i = 0
++i // i 現在等於 1
每當呼叫 ++i
時,i
的值就會增加 1
。通常來說,++i
就是 i = i + 1
的便捷寫法。類似地,--i
也相當於 i = i - 1
。
++
與 --
兩對符號可以作為字首或字尾運算子使用。++i
與 i++
均可用來將 i
的值加 1
。類似地,--i
與 i--
均可用來將 i
的值減去 1
。
注意這些運算子不僅會改變 i
的值,還會返回一個值。如果你只需要自增或自減後的值存放在 i
中,可以忽略運算子的返回值。但如果你確實要用到返回值,要注意字首及字尾運算子返回值的差異,規則如下:
如果運算子寫在變數的前面,則先改變變數值,再返回其值。
如果運算子寫在變數的後面,則先返回原值,後改變變數值。
例如:
var a = 0
let b = ++a
// a 與 b 現在均為 1
let c = a++
// a 現在為 2,但 c 被設為自增前的值 1
在上例中,let b = ++a
先增加 a
的值,然後才返回它的值。因此 a
與 b
都等於新的值 1
。
但是,let c = a++
先返回 a
的原值,然後才增加 a
的值。即 c
得到了原值 1
,然後 a
被更新為新值 2
。
除非你需要利用 i++
的這一特性,建議你在所有情況下都使用 ++i
與 --i
,因為它們的動作符合傳統思維的期望:先修改 i
的值,然後返回改變後的結果。
一元減號運算子
可以在數值前面加上 -
來切換符號。這個字首運算子 -
就稱為一元減號運算子(unary minus operator):
let 三 = 3
let 負三 = -三 // 負三 等於 -3
let 正三 = -負三 // 正三 等於 3,即“負負三”
一元減號運算子(-
)直接加在所要操作的值之前,無需任何空格。
一元加號運算子
一元加號運算子(unary plus operator,+
)直接返回所操作的值,不作任何處理:
let 負六 = -6
let 還是負六 = +負六 // 還是負六 等於 -6
儘管一元加號運算子實際上不作任何運算,程式碼中仍然可以用它提供一些語義資訊,與表示負數的一元減號運算子形成對比。
組合賦值運算子
與 C 語言類似,Swift 也提供組合賦值運算子(compound assignment operator),可將賦值運算子(=
)與其他運算組合起來使用。例如加法賦值運算子(addition assignment operator,+=
):
var a = 1
a += 2
// a 現在等於 3
表示式 a += 2
是 a = a + 2
的便捷寫法。加法與賦值操作被組合到一起,單個運算子就可以完成兩項操作,非常高效。
注:組合賦值運算子不返回值。因此不能寫成如
let b = a += 2
。該行為與前文提到的自增/自減運算子不同。
組合運算子的完整列表可在 語言參考:表示式 一節找到。
比較運算子
Swift 支援標準 C 的全部比較運算子(comparison operator):
等於(
a == b
)不等於(
a != b
)大於(
a > b
)小於(
a < b
)大於或等於(
a >= b
)小於或等於(
a <= b
)
注:Swift 還提供了兩個鑑別運算子(identity operator,
===
與!==
),可用來測試兩個物件引用是否指向同一個物件例項。詳情請見 類與結構 一節。
每個比較運算子都會返回一個 Bool
值,告知語句是否成立:
1 == 1 // true,因為 1 等於 1
2 != 1 // true,因為 2 不等於 1
2 > 1 // true,因為 2 大於 1
1 < 2 // true,因為 1 小於 2
1 >= 1 // true,因為 1 大於或等於 1
2 <= 1 // false,因為 2 既不小於又不等於 1
通常在條件語句中使用比較運算子,如在 if
語句中:
let name = "world"
if name == "world" {
println("hello, world")
} else {
println("不好意思啊,\(name),俺不認得你")
}
// 輸出 "hello, world",因為 name 的確等於 "world"
關於 if
語句的更多情況,請見 流程控制。
三元條件運算子
三元條件運算子(ternary conditional operator)是一種特殊的運算子,由三部分組成,形式為 問題 ? 回答1 : 回答2
。它根據 問題
成立與否,從兩個表示式中取出一個並求值。如果 問題
成立,則求 回答1
的結果並返回其值;否則求出 回答2
的結果並返回其值。
三元條件運算子是下述程式碼的便捷寫法:
if 問題 {
回答1
} else {
回答2
}
下面的例子將計算表格某行的顯示高度。如果該行有表頭,則行高應比內容高度高 50 個畫素;如果沒有表頭,則只高出 20 個畫素:
let 內容高度 = 40
let 有表頭 = true
let 行高 = 內容高度 + (有表頭 ? 50 : 20)
// 行高 等於 90
上例是下列程式碼的便捷寫法:
let 內容高度 = 40
let 有表頭 = true
var 行高 = 內容高度
if 有表頭 {
行高 = 行高 + 50
} else {
行高 = 行高 + 20
}
// 行高 等於 90
使用三元條件運算子的例子說明,可以僅用一行程式碼就將 行高
設為正確的值。這比不用三元運算子的第二個例子簡明得多,並且 行高
無需定義為變數,因為不再需要用 if
語句修改其值。
三元條件運算子提供了二選一的高效寫法。 但使用三元條件運算子應小心。如果過度使用,其簡明性可能導致程式碼難以閱讀。應避免將多個三元條件運算子組合在同一個語句中。
區間運算子
Swift 包含兩個區間運算子(range operator),是表達值域範圍的便捷寫法。
閉區間運算子
閉區間運算子(closed range operator,a...b
)定義了從 a
到 b
的區間範圍,包括 a
與 b
兩個值。
閉區間運算子在需要遍歷某區間內所有值時有用,如在 for
-in
迴圈中使用:
for i in 1...5 {
println("\(i) 乘以 5 得 \(i * 5)")
}
// 1 乘以 5 得 5
// 2 乘以 5 得 10
// 3 乘以 5 得 15
// 4 乘以 5 得 20
// 5 乘以 5 得 25
關於 for
-in
迴圈的更多資訊,請見 流程控制。
半閉區間運算子
半閉區間運算子(half-closed range operator,a..b
)定義了從 a
到 b
的區間,但不含 b
。說是半閉,是因為第一個值包含在區間以內,但最後一個值不在區間內。
半閉區間在處理從 0 開始計數的列表時有用,如遍歷陣列,可從 0 數到列表的長度(但不包括長度值本身):
let 名單 = ["Anna", "Alex", "Brian", "Jack"]
let 人數 = 名單.count
for i in 0..人數 {
println("第 \(i + 1) 個人叫 \(名單[i])")
}
// 第 1 個人叫 Anna
// 第 2 個人叫 Alex
// 第 3 個人叫 Brian
// 第 4 個人叫 Jack
注意陣列包含四個物件,但因為是半閉區間,所以 0..人數
只數到 3
(陣列中最後一個元素的索引號)。陣列的詳細情況請見 陣列。
邏輯運算子
邏輯運算子(logical operator)操作或組合布林邏輯值 true
與 false
。Swift 支援 C 及其衍生語言的三種標準邏輯運算子:
邏輯非(
!a
)邏輯與(
a && b
)邏輯或(
a || b
)
邏輯非運算子
邏輯非運算子(logical NOT operator,!a
)將布林值取反,即 true
變為 false
,而 false
變為 true
。
邏輯非運算子屬於字首運算子,置於所操作的值之前,不加任何空格。可以理解為“非 a
”(not a
),如下例所示:
let 允許進入 = false
if !允許進入 {
println("ACCESS DENIED")
}
// 輸出 "ACCESS DENIED"(拒絕訪問)
程式碼中的 if !允許進入
可以解釋成“如果不允許進入(if not 允許進入)”。下面一行程式碼僅當“不允許進入”成立時才會執行;即 允許進入
為 false
時才執行。
正如該例所展示的,布林值常量及變數的名稱應謹慎選擇,方可確保程式碼簡明又具可讀性,同時避免出現雙重否定或引起混淆的邏輯語句。
邏輯與運算子
邏輯與運算子(logical AND operator,a && b
)用於構造這樣的邏輯表示式:運算子兩側的值均為 true
,整個表示式的求值結果才為 true
。
如果有一個值為 false
,整個表示式便為 false
。事實上,如果第一個值為 false
,第二個值將被直接忽略,而不會進一步對它求值,因為不論它為何值,整個表示式的值都不可能等於 true
。這稱為短路求值(short-circuit evaluation)。
下例考察兩個 Bool
值,僅當兩值均為 true
時才允許訪問:
let 已輸入門禁密碼 = true
let 已通過視網膜掃描 = false
if 已輸入門禁密碼 && 已通過視網膜掃描 {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// 輸出 "ACCESS DENIED"
邏輯或運算子
邏輯或運算子(logical OR operator,a || b
)屬於中綴運算子,由兩個連續的豎線構成。它用來構造這樣的表示式:整個表示式為 true
的條件為,兩個值中至少有一個為 true
。
與前文的邏輯與運算子一樣,邏輯或運算子在考察它的兩個表示式時,也採用“短路求值”演算法。只要邏輯或表示式左側為 true
,其右側將不再求值,因為這時右側的值對整個表示式的總體結果不再有影響。
下例中,第一個 Bool
值(有鑰匙
)為 false
,但第二個值(知道備用密碼
)為 true
。因為有一個值為 true
,所以整個表示式的求值結果也為 true
,因此允許訪問:
let 有鑰匙 = false
let 知道備用密碼 = true
if 有鑰匙 || 知道備用密碼 {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// 輸出 "Welcome!"
組合使用邏輯運算子
多個邏輯運算子可以組合起來,構成更長的組合表示式:
if 已輸入門禁密碼 && 已通過視網膜掃描 || 有鑰匙 || 知道備用密碼 {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// 輸出 "Welcome!"
該例用到了多個 &&
及 ||
運算子,構造了一條更長的組合表示式。不過,&&
與 ||
運算子操作的仍然是兩個值,因此該組合表示式實際上是由三個較短的表示式連立而成的。它可以這樣理解:
如果我們輸入了正確的門禁密碼、並且通過了視網膜掃描;或者如果我們有門鑰匙;或者如果我們知道緊急的備用密碼,則允許訪問。
根據 已輸入門禁密碼
、已通過視網膜掃描
、有鑰匙
三個常量,前兩個小表示式的值均為 false
。不過我們知道緊急的備用密碼,因此整個組合表示式的求值結果仍然為 true
。
顯式括號
有時雖然從語法上看,括號並不是必需的,加上括號卻很有用,它可以讓複雜表示式的意圖更顯而易見。 在上面門禁的例子中,為組合表示式的第一部分加上括號,可使其意圖更明顯:
if (已輸入門禁密碼 && 已通過視網膜掃描) || 有鑰匙 || 知道備用密碼 {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// 輸出 "Welcome!"
括號將前兩個值與其他值分隔開來,使其構成整體邏輯中一種可能狀態的意圖更為明顯。組合表示式的結果不會改變,但對讀者而言,整體意圖更加清晰。可讀性總是優先於簡潔度;應儘可能在合適的地方使用括號,使你的意圖更加明晰。
相關文章
- Swift語言指南(九)--基本運算子Swift
- Swift--基本運算子Swift
- GO語言————4.5 基本型別和運算子Go型別
- Go語言運算子Go
- Go 語言運算子Go
- C語言運算子C語言
- java基本語法--運算子Java
- Go語言常用的運算子篇Go
- c語言運算子詳解C語言
- 關於C語言的位運算子C語言
- Go語言學習(7) - 運算子Go
- SQL語言運算子與函式SQL函式
- Swift 自定義運算子Swift
- C 語言運算子優先順序
- c語言-運算子,陣列,指標C語言陣列指標
- C語言運算子優先順序C語言
- Swift中自定義運算子Swift
- swift 區間運算子(... 和 ..Swift
- iOS Swift邏輯運算子iOSSwift
- C語言學習筆記--C運算子C語言筆記
- 逍遙自在學C語言 | 算數運算子C語言
- 逍遙自在學C語言 | 關係運算子C語言
- 逍遙自在學C語言 | 邏輯運算子C語言
- C語言位運算子及常見用法C語言
- C語言運算子深度解析--超詳細C語言
- shell指令碼——基本運算子指令碼
- 07-C語言運算子-指趣學院C語言
- 手寫程式語言-實現運算子過載
- 逍遙自在學C語言 | 位運算子的基礎用法C語言
- 逍遙自在學C語言 | 位運算子&的高階用法C語言
- 逍遙自在學C語言 | 位運算子^的高階用法C語言
- C語言常被搞錯的運算子優先順序C語言
- swift 基礎筆記二(運算子)Swift筆記
- Swift中 Nil Coalescing 運算子的使用技巧Swift
- day02 Java基本語法( 上 ): 變數與運算子Java變數
- day_07C語言運算子及流程控制C語言
- swift高階運算子-讀書筆記Swift筆記
- swift 自定義正規表示式運算子 =~Swift