diff --git a/source/chapter2/02_Basic_Operators.md b/source/chapter2/02_Basic_Operators.md index 63964fa5..0d2f50c7 100644 --- a/source/chapter2/02_Basic_Operators.md +++ b/source/chapter2/02_Basic_Operators.md @@ -1,26 +1,26 @@ # 基础运算符 -运算符是检查, 改变, 合并值的特殊符号或短语. 例如, 加号`+`把计算两个数的和(如 `let i = 1 + 2`). 复杂些的运行算包括逻辑与`&&`(如 `if enteredDoorCode && passedRetinaScan`), 还有自增运算符 `++i`, 这一个自身加一的快捷操作. +运算符是检查, 改变, 合并值的特殊符号或短语. 例如, 加号 `+` 把计算两个数的和(如 `let i = 1 + 2`). 复杂些的运行算包括逻辑与`&&`(如 `if enteredDoorCode && passedRetinaScan`), 还有自增运算符 `++i` 这样让自身加一的便捷运算. -Swift支持大部分标准C的运算符, 且改进许多项来获得减少常规编码错误. 赋值符`=`不返回值, 以防止出现错把等号 `==` 写成赋值号 `=` 导致的Bug. 数值运算符(`+`, `-`, `*`, `/`, `%`等)会检测并不允许值溢出, 以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果. 你可以选择使用Swift的溢出运算符来玩溢出. 具体使用请移步[溢出运算符](http://#). +Swift支持大部分标准C语言的运算符, 且改进许多特性来减少常规编码错误. 如, 赋值符 `=` 不返回值, 以防止错把等号 `==` 写成赋值号 `=` 而导致Bug. 数值运算符( `+` , `-`, `*`, `/`, `%`等)会检测并不允许值溢出, 以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果. 当然允许你选择使用Swift的溢出运算符来玩溢出. 具体使用请移步[溢出运算符](Overflow Operators). -与C不同, Swift中你可以对浮点数进行取余运算(`%`). Swift也提供在C语言没有的表达两数之间的区间运算符, (`a..b`和`a...b`),这方便我们表达一个区间的数值. +区别于C语言, 在Swift中你可以对浮点数进行取余运算( `%` ), 还提供了C语言没有的表达两数之间的值的区间运算符, ( `a..b` 和 `a...b` ), 这方便我们表达一个区间内的数值. -本章节只描述了Swift中的常规运算符, [高级运算符](http://#)包含了高级运算符,及如何自定义运算符,及自定义类型的运算符重载. +本章节只描述了Swift中的简单运算符, [高级运算符](http://#)包含了高级运算符,及如何自定义运算符, 及如何进行自定义类型的运算符重载. # 术语 -运算符有一目,双目和三目运算符. +运算符有一目, 双目和三目运算符. -一目运算符对单一操作对象操作, 如`-a`. +一目运算符对单一操作对象操作, 如 `-a`. -一目运算符分前置符和后置运算符, 前置运算符需紧排操作对象之前, 如`!b`, 后置运算符需紧跟操作对象之后,如`i++`, +一目运算符分前置符和后置运算符, 前置运算符需紧排操作对象之前, 如 `!b`, 后置运算符需紧跟操作对象之后,如 `i++`, -双目运算符操作两个操作对象, 如`2 + 3`. 是中置的, 因为它们出现在两个操作对象之间. +双目运算符操作两个操作对象, 如 `2 + 3`. 是中置的, 因为它们出现在两个操作对象之间. -三目运算符操作三个操作对象, 跟C一样, Swift只有一个三目运算符, 就是三目条件运算符 `a ? b : c`. +三目运算符操作三个操作对象, 和C语言一样, Swift只有一个三目运算符, 就是三目条件运算符 `a ? b : c`. -受运算符影响的值叫操作数, 在表达式`1 + 2`中, 加号`+`是双目运算符, 它的两个操作数是值`1`和`2`. +受运算符影响的值叫操作数, 在表达式 `1 + 2` 中, 加号 `+` 是双目运算符, 它的两个操作数是值 `1` 和 `2`. # 赋值运算符 @@ -38,7 +38,7 @@ a = b let (x, y) = (1, 2) // 现在 x 等于 1, y 等于 2 ``` -与C和Objective-C又不同了, Swift的赋值操作并不返回任何值. 所以以下代码是错误的: +与C语言和Objective-C不同, Swift的赋值操作并不返回任何值. 所以以下代码是错误的: ```swift if x = y { @@ -46,14 +46,16 @@ if x = y { } ``` -这个特性使得你不能够再把`==`错写成`=`了, 由于`if x = y`是错误代码, Swift从底层帮你避免了这些代码错误. +这个特性使得你不无法把`==`错写成`=`了, 由于`if x = y`是错误代码, Swift从底层帮你避免了这些代码错误. # 数值运算 + Swift让所有数值类型都支持了基本的四则运算: -- 加法 (+) -- 减法 (-) -- 乘法 (*) -- 除法 (/) + +- 加法 `+` +- 减法 `-` +- 乘法 `*` +- 除法 `/` ```swift 1 + 2 // 等于 3 @@ -62,9 +64,9 @@ Swift让所有数值类型都支持了基本的四则运算: 10.0 / 2.5 // 等于 4.0 ``` -又与C和Objective-C不一样了, Swift默认不允许数值运算出现溢出. 但你可以使用Swift的溢出运算符来达到你的目的, (如 `a &+ b` ). 详情请移步: [溢出运算符](http://#). +与C语言和Objective-C不同的是, Swift默认不允许在数值运算中出现溢出情况. 但你可以使用Swift的溢出运算符来达到你有目的的溢出, (如 `a &+ b` ). 详情请移步: [溢出运算符](Overflow Operators). -加法操作也可以用于字符串的拼接: +加法操作 `+` 也用于字符串的拼接: ```swift "hello, " + "world" // 等于 "hello, world" @@ -73,28 +75,44 @@ Swift让所有数值类型都支持了基本的四则运算: 两个字符类型或一个字符类型和一个字符串类型, 相加会生成一个新的字符串类型: ```swift -let dog: Character = "🐶" -let cow: Character = "🐮" +let dog: Character = "d" +let cow: Character = "c" let dogCow = dog + cow -// dogCow 现在是 "🐶🐮" +// 译者注: 原谅的引号内是很可爱的小狗和小牛, 但win os下不支持表情字符, 所以改成了普通字符 +// dogCow 现在是 "dc" ``` 详细请点击 [字符,字符串的拼接](http://#). -‌# 求余运算 +# 求余运算 -求余运算`a % b`是计算 `b` 的多少倍刚好可以装进 `a` , 多出来的那部分叫余数. +求余运算 `a % b` 是计算 `b` 的多少倍刚刚好可以容入 `a` , 多出来的那部分叫余数. > 注意 -> 求余运算(%)在其他语言也叫取模运算. 然而, 鉴于在Swift中该运算符对负数的操作结果, 严格来说, 求余比取模更合适些. +> 求余运算(%)在其他语言也叫取模运算. 然而严格说来, 我们看该运算符对负数的操作结果, `求余` 比 `取模` 更合适些. -我们来谈谈取余是怎么回事, 计算 `9 % 4`, 你先计算出4的多少倍会刚好可以装进`9`中. -2, 好的, 余数是1 (用橙色标出) +我们来谈谈取余是怎么回事, 计算 `9 % 4`, 你先计算出4的多少倍会刚好可以容入 `9` 中. -```swift -传说这里有张求余数的图... -传说这里有张求余数的图... -``` +2倍, 非常好, 那余数是1 (用'*'标出) + + + + + + + + + + + + + + + + + + +
1 2 3 4 5 6 7 8 9
441*
在Swift中这么来表达 @@ -102,32 +120,32 @@ let dogCow = dog + cow 9 % 4 // 等于 1 ``` -为了得到`a % b`的结果, `%`计算了以下等式, 并输出`余数`作为结果: +为了得到 `a % b` 的结果, `%`计算了以下等式, 并输出`余数`作为结果: ``` -a = (b × `倍数`) + `余数` +a = (b × 倍数) + 余数 ``` -当`倍数`取最大值的时候, 就会刚好可以装进 `a` 中. +当`倍数`取最大值的时候, 就会刚好可以容入 `a` 中. -把 `9` 和 `4` 代入等式中: +把 `9` 和 `4` 代入等式中, 我们得 `1`: ```swift 9 = (4 × 2) + 1 ``` -同样的方法, 我来们计算`-9 % 4`: +同样的方法, 我来们计算 `-9 % 4` : ``` --9 % 4 // equals -1 +-9 % 4 // 等于 -1 ``` -把 `-9` 和 4 代入等式: +把 `-9` 和 `4` 代入等式, `-2` 是取到的最大整数: ```swift -9 = (4 × -2) + -1 ``` -等于余数是-1. +余数是 `-1`. -在对负数的 `b` 求余时, `b`的符号会被忽略. 这意味着 `a % b` 和 `a % -b`的结果是相同的. +在对负数 `-b` 求余时, `-b`的符号会被忽略. 这意味着 `a % b` 和 `a % -b`的结果是相同的. ## 浮点数求余计算 @@ -148,14 +166,15 @@ var i = 0 ++i // 现在 i = 1 ``` -调用一次 `++i`, `i` 的值就会加1. +每调用一次 `++i`, `i` 的值就会加1. 实际上, `++i` 是 `i = i + 1` 的简写, 而 `--i` 是 `i = i - 1`的简写. `++` 和 `--`既是前置又是后置运算. `++i`, `i++`, `--i` 和 `i--` 都是有效的写法. -我们需要注意的是这些运算符修改了 `i` 后有一个返回值. 如果你只想修改 `i` 的值, 那你就忽略这个返回值. 但如果你想使用返回值, 你就要留意前置和后置操作的返回值是不同的. +我们需要注意的是这些运算符修改了 `i` 后有一个返回值. 如果你只想修改 `i` 的值, 那你就可以忽略这个返回值. 但如果你想使用返回值, 你就需要留意前置和后置操作的返回值是不同的. 当 `++` 前置的时候, 先自増再返回. + 当 `++` 后置的时候, 先返回再自增. 不懂? 我们看例子: @@ -175,9 +194,6 @@ let c = a++ // a 现在 2, 但 c 是 a 自增前的值 1 # 单目负号 - - -Unary Minus Operator 数值的正负号可以使用前缀 `-` (即单目负号) 来切换: ```swift @@ -186,22 +202,22 @@ let minusThree = -three // minusThree 等于 -3 let plusThree = -minusThree // plusThree 等于 3, o或 "负负3" ``` -单目负号写在需要操作的值之前, 之间不要空格. +单目负号写在操作数之前, 中间没有空格. # 单目正号 -单目正号 `+` 不做任何改变地返回被操作的值. +单目正号 `+` 不做任何改变地返回操作数的值. ```swift let minusSix = -6 let alsoMinusSix = +minusSix // alsoMinusSix 等于 -6 ``` -虽然单目`+`做无用功, 但当你在使用单目负号来表达负数时, 你可以使用单目正号来表达正数, 如此你的代码会具有对称美. +虽然单目 `+` 做无用功, 但当你在使用单目负号来表达负数时, 你可以使用单目正号来表达正数, 如此你的代码会具有对称美. # 复合赋值 -C的影子又来了, Swift也提供把其他运算符和赋值运算 `=` 组合的复合赋值运算符, 加赋运算 `+=` 是其中一个例子: +如同强大的C语言, Swift也提供把其他运算符和赋值运算 `=` 组合的复合赋值运算符, 加赋运算 `+=` 是其中一个例子: ```swift var a = 1 @@ -215,13 +231,10 @@ a += 2 // a 现在是 3 > 复合赋值运算没有返回值, `let b = a += 2` 这类代码是错误. 这不同于上面提到的自增和自减运算符. [表达式](http://#)里有复合运算符的完整列表. - ‌ # 比较运算 所有标准C中的比较运算都可以在Swift中使用. -Comparison Operators -Swift supports all standard C comparison operators: - 等于 `a == b` - 不等于 `a != b` @@ -234,7 +247,7 @@ Swift supports all standard C comparison operators: > Swift也提供恒等 `===` 和不恒等 `!==` 这两个比较符来判断两个对象是否引用同一个对象实例. 更多细节在 [类与结构](Classes and Structures). -每个比较运算都返回了一个指示表达式是否成立的布尔值: +每个比较运算都返回了一个标识表达式是否成立的布尔值: ```swift 1 == 1 // true, 因为 1 等于 1 @@ -256,13 +269,14 @@ if name == "world" { } // 输出 "hello, world", 因为 `name` 就是等于 "world" ``` + 关于 `if` 语句, 请看 [控制流](Control Flow). -‌# 三目条件运算 +# 三目条件运算 -这是一个特殊的有三个部分的运算符, 它的形式是 `问题 ? 答案1 : 答案2`. 它是根据 `问题` 成立与否作出二选一操作的简化表达. 如果 `问题` 成立, 返回 `答案1` 的结果; 如果不成立, 返回 `答案2` 的结果. +三目条件运算的特殊在于它是有三个操作数的运算符, 它的原型是 `问题 ? 答案1 : 答案2`. 它简洁地表达根据 `问题` 成立与否作出二选一的操作. 如果 `问题` 成立, 返回 `答案1` 的结果; 如果不成立, 返回 `答案2` 的结果. -三目条件运算是以下代码的精简表达: +使用三目条件运算简化了以下代码: ```swift if question: { @@ -273,7 +287,7 @@ else { } ``` -这里有个计算表格行高的例子. 如果有表头, 那行高应比内容高度高出50像素; 如果没有表头, 只需高出20像素. +这里有个计算表格行高的例子. 如果有表头, 那行高应比内容高度要高出50像素; 如果没有表头, 只需高出20像素. ```swift let contentHeight = 40 @@ -282,7 +296,7 @@ let rowHeight = contentHeight + (hasHeader ? 50 : 20) // rowHeight 现在是 90 ``` -这代码会比下面的代码简单: +这样写会比下面的代码简洁: ```swift let contentHeight = 40 @@ -296,7 +310,7 @@ if hasHeader { // rowHeight 现在是 90 ``` -第一段代码例子使用了三目条件运算, 所以一行代码就能得到正确答案. 这比第二段代码简洁得多, 无需将 `rowHeight` 定义成变量, 因它的值不用在 `if` 语句中改变. +第一段代码例子使用了三目条件运算, 所以一行代码就能让我们得到正确答案. 这比第二段代码简洁得多, 无需将 `rowHeight` 定义成变量, 因为它的值无需在 `if` 语句中改变. 三目条件运算提供有效率且便捷的方式来表达二选一的选择. 需要注意的事, 过度使用三目条件运算就会由简洁的代码变成难懂的代码. 我们应避免在一个组合语句使用多个三目条件运算符. @@ -340,7 +354,8 @@ for i in 0..count { // 第 3 个人叫 Brian // 第 4 个人叫 Jack ``` -> 注意数组有4个元素, 但 `0..count` 只数到 3 (最后一个元素的下标), 因为它是半闭区间. 关于数组, 请查阅 [数组](Arrays). + +> 注意: 数组有4个元素, 但 `0..count` 只数到 3 (最后一个元素的下标), 因为它是半闭区间. 关于数组, 请查阅 [数组](Arrays). # 逻辑运算 @@ -349,7 +364,7 @@ for i in 0..count { - 逻辑非 `!a` - 逻辑与 `a && b` - 逻辑或 `a || b` -‌ + ## 逻辑非 逻辑非运算 `!a` 对一个布尔值取反, 使得 `true` 变 `false`, `false` 变 `true`. @@ -369,9 +384,9 @@ if !allowedEntry { 在示例代码中, 小心地选择布尔常量或变量有助于代码的可读性, 并且避免使用双重逻辑非运算, 或混乱的逻辑语句. ## 逻辑与 -逻辑与 `a && b` 表达了只有 `a` 和 `b` 的值都为 `true` 时, 整个表达式的值才会 `true` . +逻辑与 `a && b` 表达了只有 `a` 和 `b` 的值都为 `true` 时, 整个表达式的值才会是 `true` . -只要任意一个值为 `false`, 整个表达式的值就为 `false`. 事实上, 如果第一个值为 `false`, 那么第二个值是不会被计算的, 因为它已经不可能影响整个表达式的结果了. 这被叫做 "短路计算". +只要任意一个值为 `false`, 整个表达式的值就为 `false`. 事实上, 如果第一个值为 `false`, 那么是不去计算第二个值的, 因为它已经不可能影响整个表达式的结果了. 这被称做 "短路计算". 以下例子, 只有两个值都为值的时候才允许进入: @@ -386,10 +401,10 @@ if enteredDoorCode && passedRetinaScan { // 输出 "ACCESS DENIED ``` -逻辑或 -逻辑或 `a || b` 是一个由两个相邻的竖线组成的中置运算符. 它表达了两个逻辑表达式的其中一个为 `true`, 整个表达式就为 `true`. +## 逻辑或 +逻辑或 `a || b` 是一个由两个连续的 `|` 组成的中置运算符. 它表示了两个逻辑表达式的其中一个为 `true`, 整个表达式就为 `true`. -同逻辑与运算类似, 逻辑或也是"短路计算", 当左端的表达式为真是, 右边的表达式就不进行计算了, 因为它也可能改变整个表达式的值了. +同逻辑与运算类似, 逻辑或也是"短路计算"的, 当左端的表达式为 `true` 时, 将不计算右边的表达式了, 因为它不可能改变整个表达式的值了. 以下示例代码中, 第一个布尔值 `hasDoorKey` 为 `false`, 但第二个值 `knowsOverridePassword` 为 `true`, 所以整个表达是 `true`, 于是允许进入: @@ -402,9 +417,9 @@ if hasDoorKey || knowsOverridePassword { println("ACCESS DENIED") } // 输出 "Welcome!" -‌``` +``` -# 组合逻辑 +## 组合逻辑 我们可以组合多个逻辑运算来表达一个复合逻辑: @@ -417,16 +432,15 @@ if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword { // 输出 "Welcome!" ``` -这个例子使用了含多个 `&&` 和 `||` 的复合逻辑. 但无论怎样, `&&` 和 `&&` 始终只能操作两个值. 所以这实际是三个简单逻辑连续操作的结果. 我们来解读一下: +这个例子使用了含多个 `&&` 和 `||` 的复合逻辑. 但无论怎样, `&&` 和 `||` 始终只能操作两个值. 所以这实际是三个简单逻辑连续操作的结果. 我们来解读一下: 如果我们输入了正确的密码并通过了视网膜扫描; 或者我们有一把有效的钥匙; 又或者我们知道紧急情况下重置的密码, 我们就能把门打开进入. -前两种情况, 我们都不满足, 所以前两个简单逻辑的结果是 `false`, 但是我们知道紧急情况下重置的密码, 所以整个复杂表达式的值还是 `true`. +前两种情况, 我们都不满足, 所以前两个简单逻辑的结果是 `false`, 但是我们是知道紧急情况下重置的密码的, 所以整个复杂表达式的值还是 `true`. +## 使用括号来明确优先级 -‌## 使用括号来明确优先级 - -为了一个复杂表达式更容易读懂, 在合适的地方使用括号来明确优先级是很有效的, 虽然它并不是必要的. 在上个关于门的权限的例子中, 我们给第一个部分加个括号, 使用它看起来更准确. +为了一个复杂表达式更容易读懂, 在合适的地方使用括号来明确优先级是很有效的, 虽然它并非必要的. 在上个关于门的权限的例子中, 我们给第一个部分加个括号, 使用它看起来逻辑更明确. ```swift if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword { @@ -437,4 +451,6 @@ if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword // prints "Welcome!" ``` -这括号使得前两个值被看成整个逻辑表达中独立的一个部分. 有括号和没括号的输出结果是一样的, 但对于读代码的人来说有括号的代码更清晰. 可读性比简洁性更重要, 请在可以让你代码变清晰地地方加个括号吧! \ No newline at end of file +这括号使得前两个值被看成整个逻辑表达中独立的一个部分. 虽然有括号和没括号的输出结果是一样的, 但对于读代码的人来说有括号的代码更清晰. + +可读性比简洁性更重要, 请在可以让你代码变清晰地地方加个括号吧! \ No newline at end of file