demo 地址:https://share.weiyun.com/5gIsJHA
运算符是一个符号,用于告诉编译器执行一个数学或逻辑运算。
Swift 提供了以下几种运算符:
- 算术运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 赋值运算符
- 区间运算符
- 其他运算符
下面将为大家详细介绍算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符及其他运算符。
算术运算符
以下表格列出了 Swift 语言支持的算术运算符,其中变量 A 为 10,变量 B 为 20:
运算符 | 描述 | 实例 |
---|---|---|
+ |
加号 | A + B 结果为 30 |
− |
减号 | A - B 结果为 -10 |
* |
乘号 | A * B 结果为 200 |
/ |
除号 | B / A 结果为 2 |
% |
求余 | B % A 结果为 0 |
注意:swift3 中已经取消了
++
、--
。
实例
以下为算术运算的简单实例:
import Cocoa
var A = 10
var B = 20
print("A + B 结果为:\(A + B)")
print("A - B 结果为:\(A - B)")
print("A * B 结果为:\(A * B)")
print("B / A 结果为:\(B / A)")
A += 1 // 类似 A++
print("A += 1 后 A 的值为 \(A)")
B -= 1 // 类似 B--
print("B -= 1 后 B 的值为 \(B)")
以上程序执行结果为:
A + B 结果为:30
A - B 结果为:-10
A * B 结果为:200
B / A 结果为:2
A += 1 后 A 的值为 11
B -= 1 后 B 的值为 19
比较运算符
以下表格列出了 Swift 语言支持的比较运算符,其中变量 A 为 10,变量 B 为 20:
运算符 | 描述 | 实例 |
---|---|---|
== |
等于 | (A == B) 为 false
|
!= |
不等于 | (A != B) 为 true
|
> |
大于 | (A > B) 为 false
|
< |
小于 | (A < B) 为 true
|
>= |
大于等于 | (A >= B) 为 false
|
<= |
小于等于 | (A <= B) 为 true
|
实例
以下为比较运算的简单实例:
import Cocoa
var A = 10
var B = 20
print("A == B 结果为:\(A == B)")
print("A != B 结果为:\(A != B)")
print("A > B 结果为:\(A > B)")
print("A < B 结果为:\(A < B)")
print("A >= B 结果为:\(A >= B)")
print("A <= B 结果为:\(A <= B)")
以上程序执行结果为:
A == B 结果为:false
A != B 结果为:true
A > B 结果为:false
A < B 结果为:true
A >= B 结果为:false
A <= B 结果为:true
逻辑运算符
以下表格列出了 Swift 语言支持的逻辑运算符,其中变量 A 为 true
,变量 B 为 false
:
运算符 | 描述 | 实例 |
---|---|---|
&& |
逻辑与;如果运算符两侧都为 true 则为 true
|
(A && B) 为 false
|
|| |
逻辑或;如果运算符两侧至少有一个为 true 则为 true
|
(A || B) 为 true
|
! |
逻辑非;布尔值取反,使得true 变false ,false 变true
|
! (A && B) 为 true
|
以下为逻辑运算的简单实例:
import Cocoa
var A = true
var B = false
print("A && B 结果为:\(A && B)")
print("A || B 结果为:\(A || B)")
print("!A 结果为:\(!A)")
print("!B 结果为:\(!B)")
以上程序执行结果为:
A && B 结果为:false
A || B 结果为:true
!A 结果为:false
!B 结果为:true
位运算符
位运算符用来对二进制位进行操作:
-
~
:取反:单目运算符
具有右结合性;其功能是对参与运算的数的各二进位按位求反。
例如:
~(1001)
结果为:0110
-
&
:按位与
是双目运算符;其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。 -
|
:按位或
是双目运算符,其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。 -
^
:按位异或
是双目运算符,其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1;反之为0。参与运算数仍以补码出现。 -
<<
:左移运算符:
是双目运算符。左移n位就是乘以2的n次方。 其功能把<<
左边的运算数的各二进位全部左移若干位,由<<
右边的数指定移动的位数,高位丢弃,低位补0。- 运算规则:
按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。 - 语法格式:
需要移位的数字<<
移位的次数
- 运算规则:
注意:当最高位溢出包括1时,则不适用规则左移n位就是乘以2的n次方。
-
>>
:无符号右移运算符- 运算规则:
按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。 - 语法格式:
需要移位的数字>>
移位的次数 - 示例: 11
>>
2,则是将数字11右移2位
计算过程:
11的二进制形式为:0000 1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0000 0010。转换为十进制是2。 - 数学意义:
右移一位相当于除2,右移n位相当于除以2的n次方。这里是取商,不包括余数。
- 运算规则:
-
>>>
:有符号右移运算符- 运算规则:
按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。 其他结构和>>
相似。
- 运算规则:
p | q | p & q |
p | q |
p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
如果指定 A = 156; 及 B = 63; 两个变量对应的二进制为:
A = 1001 1100
B = 0011 1111
运算符 | 图解 | 实例 |
---|---|---|
& |
https://share.weiyun.com/52ERV3D | (A & B) 结果为 28,二进制为 0001 1100 |
| |
https://share.weiyun.com/5tKae28 | (A | B) 结果为 191,二进制为 1011 1111 |
^ |
https://share.weiyun.com/5kp5F0h | (A ^ B) 结果为 163,二进制为 1010 0011 |
~ |
https://share.weiyun.com/53vcuaN | (~ A) 结果为 99,二进制为 0110 0011 |
<< |
https://share.weiyun.com/5L085l0 | (A << 1) 结果为 312,二进制为 0001 0011 1000 |
>> |
https://share.weiyun.com/5j3GIeV | (A >> 1) 结果为 78,二进制为 0100 1110 |
以下为位运算的简单实例:
import Cocoa
var A = 60 // 二进制为 0011 1100
var B = 13 // 二进制为 0000 1101
print("A&B 结果为:\(A&B)")
print("A|B 结果为:\(A|B)")
print("A^B 结果为:\(A^B)")
print("~A 结果为:\(~A)")
以上程序执行结果为:
A&B 结果为:12
A|B 结果为:61
A^B 结果为:49
~A 结果为:-61
赋值运算
-
=
简单的赋值运算,指定右边操作数赋值给左边的操作数 -
+=
相加后再赋值,将左右两边的操作数相加后再赋值给左边的操作数 -
-=
相减后再赋值,将左右两边的操作数相减后再赋值给左边的操作数 -
*=
相乘后再赋值,将左右两边的操作数相乘后再赋值给左边的操作数 -
/=
相除后再赋值,将左右两边的操作数相除后再赋值给左边的操作数 -
%=
求余后再赋值,将左右两边的操作数求余后再赋值给左边的操作数 -
<<=
按位左移后再赋值 -
>>=
按位右移后再赋值 -
&=
按位与运算后赋值 -
^=
按位异或运算符后再赋值 -
|=
按位或运算后再赋值
运算符 | 示例 |
---|---|
= |
C = A + B 将 A + B 的运算结果赋值给 C
|
+= |
C += A 相当于 C = C + A
|
-= |
C -= A 相当于 C = C - A
|
*= |
C *= A 相当于 C = C * A
|
/= |
C /= A 相当于 C = C / A
|
%= |
C %= A 相当于 C = C % A
|
<<= |
C <<= 2 相当于 C = C << 2
|
>>= |
C >>= 2 相当于 C = C >> 2
|
&= |
C &= 2 相当于 C = C & 2
|
^= |
C ^= 2 相当于 C = C ^ 2
|
|= |
C |= 2 相当于 C = C | 2
|
以下为赋值运算的简单实例:
var A = 5; var B = 6; var C = 0
printConditionD3(A: A, B: B, C: C)
C = A + B; print("A + B 结果为 \(C)")
A = 3; C = 5; printConditionD2(A: A, C: C)
C += A; print("C += A 结果为 \(C)")
A = 10; C = 15; printConditionD2(A: A, C: C)
C -= A; print("C -= A 结果为 \(C)")
A = 6; C = 7; printConditionD2(A: A, C: C)
C *= A; print("C *= A 结果为 \(C)")
A = 4; C = 36; printConditionD2(A: A, C: C)
C /= A; print("C /= A 结果为 \(C)")
A = 3; C = 8; printConditionD2(A: A, C: C)
C %= A; print("C %= A 结果为 \(C)")
C = 0b0100; A = 0b0001; printConditionB(A: A, C: C)
C <<= A; print("C <<= A 结果为 \(numToStr(num: C))")
C = 0b100; A = 1; printConditionB(A: A, C: C)
C >>= A; print("C >>= A 结果为 \(numToStr(num: C))")
C = 0b1001; A = 0b1010; printConditionB(A: A, C: C)
C &= A; print("C &= A 结果为 \(numToStr(num: C))")
C = 0b1001; A = 0b1010; printConditionB(A: A, C: C)
C ^= A; print("C ^= A 结果为 \(numToStr(num: C))")
C = 0b1001; A = 0b1010; printConditionB(A: A, C: C)
C |= A; print("C |= A 结果为 \(numToStr(num: C))")
func numToStr(num: Int) -> String
{
return "0b\(String(format: "%04d", Int(String(num, radix: 2, uppercase: false))!))"
}
func printConditionD3(A: Int, B: Int, C: Int)
{
print("当 A = \(A)、B = \(B)、C = \(C) 时,", separator: ",", terminator: " ")
}
func printConditionD2(A: Int, C: Int)
{
print("当 A = \(A)、C = \(C) 时,", separator: ",", terminator: " ")
}
func printConditionB(A: Int, C: Int)
{
print("当 A = \(numToStr(num: A))、C = \(numToStr(num: C)) 时,", separator: ",", terminator: " ")
}
执行结果为:
当 A = 5、B = 6、C = 0 时, A + B 结果为 11
当 A = 3、C = 5 时, C += A 结果为 8
当 A = 10、C = 15 时, C -= A 结果为 5
当 A = 6、C = 7 时, C *= A 结果为 42
当 A = 4、C = 36 时, C /= A 结果为 9
当 A = 3、C = 8 时, C %= A 结果为 2
当 A = 0b0001、C = 0b0100 时, C <<= A 结果为 0b1000
当 A = 0b0001、C = 0b0100 时, C >>= A 结果为 0b0010
当 A = 0b1010、C = 0b1001 时, C &= A 结果为 0b1000
当 A = 0b1010、C = 0b1001 时, C ^= A 结果为 0b0011
当 A = 0b1010、C = 0b1001 时, C |= A 结果为 0b1011
区间运算符
Swift 提供了两个区间的运算符:闭区间运算符(...
)和半开区间运算符(..<
)
- 闭区间运算符(
...
)
闭区间运算符(a...b)定义一个包含从a到b(包括a和b)的所有值的区间,b必须大于等于a。 闭区间运算符在迭代一个区间的所有值时是非常有用的,如在for-in循环中。 - 半开区间运算符(
..<
)
半开区间(a..<b)定义一个包含从 a 到 b(包括a,不包括 b)的所有值的区间,b 必须大于a。
运算符 | 实例 |
---|---|
闭区间运算符(... ) |
1... 5 区间值为 1, 2, 3, 4 和 5 |
半开区间运算符(..< ) |
1..< 5 区间值为 1, 2, 3, 和 4 |
以下为区间运算的简单实例:
import Cocoa
print("闭区间运算符:")
for index in 1...5 {
print("\(index) * 5 = \(index * 5)")
}
print("半开区间运算符:")
for index in 1..<5 {
print("\(index) * 5 = \(index * 5)")
}
以上程序执行结果为:
1 * 5 = 5
2 * 5 = 10
3 * 5 = 15
4 * 5 = 20
5 * 5 = 25
半开区间运算符:
1 * 5 = 5
2 * 5 = 10
3 * 5 = 15
4 * 5 = 20
空合运算符
这个操作符可以用来快速的对 nil 进行判断,当左侧的值是 非 nil时返回其value左侧的值,为nil时返回其右侧的值。
两个条件:表达式a必须是可选类型,默认值b的类型必须要和a存储值的类型一致。空合并运算符 (a ??
b) 将对可选类型a进行空判断,如果a包含一个值就进行解封,否则就返回一个默认值b。
//空合运算符
var strResult : String?
let strDefault = "default string"
var strNew = strResult ?? strDefault
print("strNew:\(strNew)")
strResult = "result string"
strNew = strResult ?? strDefault
print("strNew:\(strNew)")
以上程序的执行结果为:
strNew:default string
strNew:result string
其他运算符
Swift 提供了其他类型的的运算符,如一元、二元和三元运算符。
- 一元运算符对单一操作对象操作(如-a)。一元运算符分前置运算符和后置运算符,前置运算符需紧跟在操作对象之前(如!b),后置运算符需紧跟在操作对象之后(例如c!)。
备注:在Java/C没有类似c!的语法, 在Swift中用在Optional类型取值。
- 二元运算符操作两个操作对象(如2 + 3),是中置的,因为它们出现在两个操作对象之间。
- 三元运算符操作三个操作对象,和 C 语言一样,Swift 只有一个三元运算符,就是三目运算符(a ? b : c)。
运算符重载
现有一个向量,我们重载它的+
,-
,*
,+=
运算符。
注意:
=
是不可以进行重载的。
struct Vector3
{
var x: Double = 0.0
var y: Double = 0.0
var z: Double = 0.0
}
注意:以下重载函数要写在
class
外部,且只能是1个或2个参数
- 重载
+
// 重载加号(+)
func + (left: Vector3, right: Vector3) -> Vector3 {
return Vector3(x: left.x + right.x, y: left.y + right.y, z: left.z + right.z)
}
- 重载减号
-
func - (left: Vector3, right: Vector3) -> Vector3 {
return Vector3(x: left.x - right.x, y: left.y - right.y, z: left.z - right.z)
}
- 重载乘号
*
func * (left: Vector3, right: Vector3) -> Double {
return left.x * right.x + left.y * right.y + left.z * right.z
}
- 重载负号
-
/*
重载负号(-),只有一个参数
由于不知道“-”是放在参数的左侧还是右侧,
故需要添加关键字prefix,代表“-”是在参数的左侧
*/
prefix func - (value: Vector3) -> Vector3 {
return Vector3(x: -value.x, y: -value.y, z: -value.z)
}
- 重载
+=
/*
重载 += ,
由于是把该操作会使left值发生改变,故left需要用到关键字 inout;
由于“+”方法在之前定义过,故在这个方法中可以直接使用“+”方法
*/
func += (left: inout Vector3, right: Vector3) -> Vector3 {
left = left + right
return left
}
实例
var v1 = Vector3(x: 3.0, y: 4.0, z: 5.0)
var v2 = Vector3(x: 7.0, y: 9.0, z: 6.0)
print("v1 + v2 结果为:\(v1 + v2)")
print("v1 - v2 结果为:\(v1 - v2)")
print("v1 * v2 结果为:\(v1 * v2)")
print("-v1 结果为:\(-v1)")
print("v1 += v2 结果为:\(v1 += v2)")
以上程序的执行结果为:
v1 + v2 结果为:Vector3(x: 10.0, y: 13.0, z: 11.0)
v1 - v2 结果为:Vector3(x: -4.0, y: -5.0, z: -1.0)
v1 * v2 结果为:87.0
-v1 结果为:Vector3(x: -3.0, y: -4.0, z: -5.0)
v1 += v2 结果为:Vector3(x: 10.0, y: 13.0, z: 11.0)
自定义运算符
对于系统中没有的运算符,需要通过 operator
关键字来定义操作符。
注意:这些函数仍要写在
class
外面。
- 操作符在参数后面,使用关键字
postfix
// 对于系统中没有的运算符,需要通过 operator 来定义操作符
// postfix 表示操作符应在参数的后面
postfix operator +++
postfix func +++ (vector: inout Vector3) -> Vector3 {
vector = vector + Vector3(x: 1.0, y: 1.0, z: 1.0)
return vector
}
- 操作符应在参数的前面,使用关键字
prefix
// prefix 表示操作符应在参数的前面
prefix operator ---
prefix func --- (vector: inout Vector3) -> Vector3
{
vector = vector - Vector3(x: 1.0, y: 1.0, z: 1.0)
return vector
}
- 中间运算符
infix
infix operator **<: BTPrecedenceL
precedencegroup BTPrecedenceL {
associativity: left // 左结合
higherThan: AdditionPrecedence // 优先级高于加法运算符
}
func **< (x: Double, y: Double) -> Double {
return x * y
}
infix operator **>: BTPrecedenceR
precedencegroup BTPrecedenceR {
associativity: right //右结合
lowerThan: AdditionPrecedence // 优先级低于加法运算符
}
func **> (x: Double, y: Double) -> Double {
return x * y
}
实例
var v2 = Vector3(x: 7.0, y: 9.0, z: 6.0)
print("v2+++ 结果为:\(v2+++)")
print("---v2 结果为:\(---v2)")
let a = 3.0
let b = 2.0
let c = 4.0
print("a **< b **< c = \(a **< b **< c)")
print("1.0 + a **< b **< c = \(1.0 + a **< b **< c)")
print("a **> b **> c = \(a **> b **> c)")
print("1.0 + a **> b **> c = \(1.0 + a **> b **> c)")
以上程序的执行结果为:
v2+++ 结果为:Vector3(x: 8.0, y: 10.0, z: 7.0)
---v2 结果为:Vector3(x: 7.0, y: 9.0, z: 6.0)
a **< b **< c = 24.0
// 此处先计算 a **< b **< c,再加1.0
1.0 + a **< b **< c = 25.0
a **> b **> c = 24.0
// 此处先计算 1.0 + a
1.0 + a **> b **> c = 32.0
运算符优先级
在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的运算顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
相同优先级中,按结合顺序计算。大多数运算是从左至右计算,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。
基本的优先级需要记住:
- 指针最优,单目运算优于双目运算,如正负号
- 先乘除(模),后加减
- 先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7 等价于 (1 << (3 + 2))&7
- 逻辑运算最后计算
详细的优先级参见下表:https://share.weiyun.com/5AuIR4J