首页 > 代码库 > 4.Swift基本运算符

4.Swift基本运算符

英文版PDF下载地址http://download.csdn.net/detail/tsingheng/7480427

运算符是指一个特殊的符号,可以用来查看,更改值或者相加。比如说加法运算符+可以讲两个数字加起来。还有一些复杂的例子比如逻辑与&&或者自增++。Swift支持C中得大部分运算符,并且加入了一些增强的特性来减少代码中的错误。赋值预算符=不会返回值,这样就避免了在应该使用比较运算符==的地方误用=。数学运算符(加减乘除模)会做溢出判断,这样避免了值溢出的时候出现的奇怪现象。你可以选择使用Swift提供的溢出运算来允许溢出,很后面的时候会有介绍。

Swift浮点数是可以进行求模运算的,C是不可以的。Swift还提供了范围符号(1..4和4...6)。

这张还是介绍一些通用的操作符,特殊操作符在后面Swift特殊操作符里面介绍,还会介绍怎么自定义操作符或者为自定义类实现操作符运算。

1.术语

运算符可以是一元、二元或者三元的。

  • 一元运算符只对单个值进行操作。一元运算符通常都紧贴这操作对象,前后都有。
  • 二元运算符对像个值进行操作。一般出现在两个操作对象中间。
  • 三元运算符涉及三个对象,而且Swift语言里面只有一个三元操作符。(a ? b: c)毫无疑问。

运算符影响的值叫运算元。对于表达式1+2来说,加号(+)是个二元运算符,他的两个运算元分别是1跟2。

赋值运算符

赋值运算符(a = b)使用b的值来初始化或者更新a的值。

let b = 10
var a = 5
a = b
// a is now equal to 10
如果赋值运算符右边是个元组,元组中的值可以一次性被解析出来赋值给多个变量或常量。

let (x, y) = (1, 2)
// x is equal to 1, and y is equal to 2
跟C或者OC的赋值不一样的是,Swift的赋值运算不返回值。像下面这样就是错的

if x = y {
    // this is not valid, because x = y does not return a value
}
这个特性防止了该用==的地方使用=。编译器对if x= y报错,你就能避免这类错误了。

2.数学运算符

Swift提供四个标准数学运算符支持多有的数字类型。加减乘除

1 + 2       // equals 3
5 - 3       // equals 2
2 * 3       // equals 6
10.0 / 2.5  // equals 4.0
但是默认情况下Swift数学运算符是不允许溢出的。你可以通过溢出运算符来允许溢出比如说 a &+ b;

加号运算符还能用来连接字符串 比如"hello," + "china"结果是“hello,china”。两个字符,或者一个字符跟一个字符串,都能相加得到字符串。(下面例子里面字符用的是表情符,不windows应该是不支持吧,我猜的。)

let dog: Character = "d"
let cow: Character = "c"
let dogCow = dog + cow
// dogCow is equal to "dc”
求余运算符

求余运算(a % b)是指a = n*b+c,n是整数,c要比b小,c就是结果。

NOTE 求余运算与其他语言里面的求模运算很想。但是Swift里面求余还可以是负数,所以还是叫求余运算。

这里有个图示说明求余怎么回事。加入要计算9%4,首先要计算9里面可以放几个4:

441
123456789


9里面可以放得下2个4,剩下的就是1了。

要计算a%b的结果,%运算使用公式a = (b*someMultiplier) + remainder,并且用remainder作为返回值。someMultiplier是a中能容得下b的最大数量,带入上面的例子就是9 = (4*2) + 1

当a是负数的时候也是一样的方法。 -9%4 等于-1,代入公式就是 -9 = (4*-2)+(-1),结果是就是-1,如果b是负数的话,b的负号都会呗忽略,所以a%b和a%-b的结果总是一样的。

浮点数求余运算

Swift求余运算还能用于浮点数比如8%2.5结果是0.5。实在太简单了又不好翻译这几句讲解就算了。

自增和自减运算符

跟C一样,Swift提供了自增(++)和自减(--)运算符,用来方便的使某个值加1或者减1。这两个操作符可以用于整数或者浮点数。

var i = 0
++i //i等于1了

每次你调用++i的时候i的值都会加1。++i其实就是i = i+1的缩写。一样的道理,--i就是i = i -1的缩写。

++和--既能用作前缀也能用作后缀,++i和i++都是正确地,--i和i--也是正确的(还用说吗,跟鸟哥一样啰嗦啊)

注意这两个操作符既修改i的值,最后还返回一个值,如果你只是想改变i的值,可以忽略最后的返回值,但是当你要使用返回值的时候要注意前缀跟后缀的区别。如果使用前缀,返回的是加1前的值,使用后缀返回的是加1后的值。例如

var a = 0
let b = ++a
// a and b are now both equal to 1
let c = a++
// a is now equal to 2, but c has been set to the pre-increment value of 1
上面这个例子中,let b = ++a先让a的值加1,然后才返回a的值。也就解释了为什么a跟b的值都是1了。但是let c = a++是先返回a的值然后才给a加1的。所以说这个完了以后a是2,而c等于1。

这里说建议尽量都是++i和--i的形式,我在JAVA里面都是写i++啊。

一元负运算符

数字的符号可以用-来改变,-就是个一元运算符

let three = 3
let minusThree = -three       // minusThree equals -3
let plusThree = -minusThree   // plusThree equals 3, or "minus minus three”
-直接放在操作对象的前面,中间不要有任何空格。

一元正运算符

+号运算符只是返回操作对象的值,不会有任何改变。

let minusSix = -6
let alsoMinusSix = +minusSix  // alsoMinusSix equals -6
虽然说加号不错任何改变,但是如果你代码里给负数加负号,给正数加正号就显得对称多了。

复合赋值运算

Swift也提供了复合赋值运算,用来结合赋值运算符和其他的运算符。典型的例子就是+=了

var a = 1
a += 2
// a is now equal to 3
a += 2就是a = a+2的缩写。两种方式只是第一种将两个运算符结合到一起了,两种方式执行时间是一样的。

NOTE 复合运算符没有返回值,比如说不能使用let b = a+=2。这个是跟自增自减运算不一样的地方。

3.比较运算符

Swift支持C所有的比较运算符,比较相等,比较不相等,大于,小于,大于等于,小于等于

NOTE Swift还提供了两个身份比较运算符===和!==,用来比较是两个对象的引用还是同一个对象的引用。

每个比较运算符返回值都是Bool,表示这个表达式是不是正确的。

1 == 1   // true, because 1 is equal to 1
2 != 1   // true, because 2 is not equal to 1
2 > 1    // true, because 2 is greater than 1
1 < 2    // true, because 1 is less than 2
1 >= 1   // true, because 1 is greater than or equal to 1
2 <= 1   // false, because 2 is not less than or equal to 1
比较运算符通常用在条件语句中,比如if语句

let name = "world"
if name == "world" {
    println("hello, world")
} else {
    println("I'm sorry \(name), but I don't recognize you")
}
// prints "hello, world", because name is indeed equal to "world”
4.三元条件运算符

三元条件运算符是一种特殊的运算,由三个部分组成,形式是 question ? answer1 : answer2。这是根据一个条件question是true还是false决定计算后面那个表达式。如果question是ture就计算answer1并且返回answer1的计算结果,如果是false就是answer2了。用代码表示就是这样:

if question {
    answer1
} else {
    answer2
}
下面有个例子,计算表格行的高度。如果表格有表头,行高就要比内容高50px,如果没有表头,就比内容高20px:

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90
用if来写就是这样的

let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
    rowHeight = rowHeight + 50
} else {
    rowHeight = rowHeight + 20
}
// rowHeight is equal to 90
使用三元运算符的话设置行高只要一行代码就行了。比后面用if的简介多了,还不用把rowHeight定义成变量,因为在if里面根本不需要去改变rowHeight的值。

三元运算符提供了一种高效的方式来表达两选一的情况。但是使用三元运算符的时候也要注意,如果太简洁了可能会降低代码的可读性。避免结合多个三元运算符搞成一条语句。

5.范围运算符

Swift提供两种范围运算符,用来表示数值范围

闭区间范围运算符

闭区间范围运算符(a...b)定义了从a到b得范围,并且包含a和b。当你要遍历某个范围并且需要范围里面每个值都要用到的时候就可以用范围运算符了,比如for-in循环

for index in 1...5 {
    println("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
半闭范围运算符

半闭范围运算符(a..b)定义了从a到b包含a但不包含b的范围,之所以叫半闭范围运算符就是因为只包含左边届不包含右边界。

半闭范围运算符对于遍历数组这种下标从0开始但是不包含数组长度的遍历很有用。

let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..count {
    println("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack
注意数组包含四项,但是0..count只包含到3。

6.逻辑运算符

逻辑运算符可以修改或者结合逻辑值true和false。Swift支持三种标准的逻辑操作符 非(!),与(&&),或(||)

逻辑非运算符

逻辑非运算符取相反的结果,所以true变成false,flase变成true。逻辑非运算符是前缀运算符,并且跟操作对象中间不允许有空格。可以被读作“不是a”

let allowedEntry = false
if !allowedEntry {
    println("ACCESS DENIED")
}
// prints "ACCESS DENIED"
表达式if !allowedEntry可以被读作“如果不是允许进入”,if里面的代码只有如果不是允许进入是真的时候才能执行,也就是如果允许进入是false的时候。

就像这个例子一样,给Boolean型变量或者常量取个好名字能保持代码整洁易读,尽量避免使用双重否定或者一些容易让人困惑的表达。

逻辑与操作符

对于逻辑与(a && b)操作符来说只有a跟b都是true的时候他才返回true,否则返回false。a跟b任何一个为false,整个表达式都是false,事实上,如果a是false,b就不会再去计算了,因为没有必要啊。下面例子使用了两个bool值,并且只有两个都为true的时候才能输出welcome

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
    println("Welcome!")
} else {
    println("ACCESS DENIED")
}
// prints "ACCESS DENIED”

逻辑或运算符

对于逻辑或(a || b)来说,只要a跟b有一个true,结果就反胃true。跟逻辑与一样,如果a计算结果是true,就不会再去计算b的值直接返回true了。下面的例子一个Bool值是false,但是第二个是true,两个与计算之后还是true,所以if通过

let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
    println("Welcome!")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome!”
结合逻辑运算

你可以结合多个逻辑运算组成一个更长的复合语句

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
    println("Welcome!")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome!”
上面例子用了多个&&和||组成了一个有点儿长的复合表达式。但是&&和||还是只能各自计算两个值,所以实际上是三个语句连在一起,可以解释成:

如果我们已经进入了正确的门且通过了视网膜扫描;或者如果我们有一张合法的门卡;或者如果我们认识解除紧急警报的密码,那么就可以进入。

通过对值enteredDoorCode,passedRetinaScan和hasDoorKey的计算,前两个表达式的计算结果是false,但是我们知道解除警报状态的密码,所以说整个表达式结果还是true。

7.明确的括号

有时候有些地方可以使用括号也可以不用括号,但是加上括号能让代码看起来更明了。像上面的例子,给第一部分加上括号就很有用了,代码的意图就很清晰

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
    println("Welcome!")
} else {
    println("ACCESS DENIED")
}
// prints "Welcome!”
括号表明了第一个与运算的结果是整体结果的一个独立部分,加上括号不会影响表达式计算结果,但是整体意图变得更清晰易读了。可读性总是比简洁性要重要。尽量用括号。

本章完。下章地址5.Swift字符串和字符