Swift|Swift 运算符

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 Cocoavar A = 10 var B = 20print("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 Cocoavar A = 10 var B = 20print("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
! 逻辑非;布尔值取反,使得truefalsefalsetrue !(A && B) 为 true
以下为逻辑运算的简单实例:
import Cocoavar A = true var B = falseprint("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. 运算规则:
      按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零。
    2. 语法格式:
      需要移位的数字 << 移位的次数
注意:当最高位溢出包括1时,则不适用规则左移n位就是乘以2的n次方。
  • >>:无符号右移运算符
    1. 运算规则:
      按二进制形式把所有的数字向右移动对应的位数,低位移出(舍弃),高位的空位补符号位,即正数补零,负数补1。
    2. 语法格式:
      需要移位的数字 >> 移位的次数
    3. 示例: 11 >> 2,则是将数字11右移2位
      计算过程:
      11的二进制形式为:0000 1011,然后把低位的最后两个数字移出,因为该数字是正数,所以在高位补零。则得到的最终结果是0000 0010。转换为十进制是2。
    4. 数学意义:
      右移一位相当于除2,右移n位相当于除以2的n次方。这里是取商,不包括余数。
  • >>>:有符号右移运算符
    1. 运算规则:
      按二进制形式把所有的数字向右移动对应位数,低位移出(舍弃),高位的空位补零。对于正数来说和带符号右移相同,对于负数来说不同。 其他结构和>>相似。
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 Cocoavar A = 60// 二进制为 0011 1100 var B = 13 // 二进制为 0000 1101print("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 + BA + 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 = 0printConditionD3(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..
运算符 实例
闭区间运算符(... 1...5 区间值为 1, 2, 3, 4 和 5
半开区间运算符(..< 1..<5 区间值为 1, 2, 3, 和 4
以下为区间运算的简单实例:
import Cocoaprint("闭区间运算符:") 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.0print("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
  • 逻辑运算最后计算
【Swift|Swift 运算符】详细的优先级参见下表:https://share.weiyun.com/5AuIR4J

    推荐阅读