高级运算符
1.5.1无符号
向左移或向右移动指定的位数,被移出整型存储边界的位数直接抛弃,移动过留下的空白位用零填充,称为逻辑移位
1.5.2有符号
有符号整型通过第一个比特位来表达这个数是整数还是负数,0代表正数,1代表负数
有符整型在右移的时候,使用符号位(0/1)填补右移产生的空白,以确保有符号的整型在右移的时候符号不会发生变化
如果有意在溢出时对有效位进行截断,可采用溢出运算,Swift提供5个&字符开头的溢出运算符
在func之前写上属性 @infix 即可定义一个全局的 + 函数
新的运算符声明需要在全局使用operator关键字声明,可以声明为前置,中置或后置
定义一个新的前置运算符 +++
1.位运算符
1.1按位取反
前置运算符 ~ 对一个操作数的每一位都取反,后紧跟操作数,不加空格let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits // equals 11110000
1.2按位与
对两个数进行操作,返回一个新的数,两个数的同一位都为1时,输出数才为1let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8 = 0b00111111
let middleFourBits = firstSixBits & lastSixBits // equals 00111100
1.3按位或
比较两个数,返回一个新的数,两个数的同一位都不为0时,输出数才为1let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits // equals 11111110
1.4按位异或
比较两个数返回一个新的数,两个数的同一位不同时,输出数才为1,相同输出0let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits // equals 00010001
1.5按位左移/右移
把一个数的比特位按定义的规则向左或向右移动指定的位数,相当于把一个整数乘以或除以一个因子为2的整数,左移相当于乘以2,右移相当于除以21.5.1无符号
向左移或向右移动指定的位数,被移出整型存储边界的位数直接抛弃,移动过留下的空白位用零填充,称为逻辑移位
let shiftBits: UInt8 = 4 // 00000100 in binary
shiftBits << 1 // 00001000
shiftBits << 2 // 00010000
shiftBits << 5 // 10000000
shiftBits << 6 // 00000000
shiftBits >> 2 // 00000001
let pink: UInt32 = 0xCC6699
let redComponent = (pink & 0xFF0000) >> 16 // redComponent is 0xCC, or 204
let greenComponent = (pink & 0x00FF00) >> 8 // greenComponent is 0x66, or 102
let blueComponent = pink & 0x0000FF // blueComponent is 0x99, or 153
1.5.2有符号
有符号整型通过第一个比特位来表达这个数是整数还是负数,0代表正数,1代表负数
有符整型在右移的时候,使用符号位(0/1)填补右移产生的空白,以确保有符号的整型在右移的时候符号不会发生变化
2.溢出运算符
默认Swift不允许往一个整型常量赋予一个它无法承载的大数,这样在操作过大或过小的数时就会很安全// Int16整型能接受的范围是-32768到32767之间,
var potentialOverflow = Int16.max
// potentialOverflow equals 32767, which is the largest value an Int16 can hold
potentialOverflow += 1
// this causes an error
如果有意在溢出时对有效位进行截断,可采用溢出运算,Swift提供5个&字符开头的溢出运算符
2.1值的上溢出 (&+)
var willOverflow = UInt8.max
// willOverflow equals 255, which is the largest value a UInt8 can hold
willOverflow = willOverflow &+ 1
// willOverflow is now equal to 0
2.2值的下溢出 (&-)
var willUnderflow = UInt8.min
// willUnderflow equals 0, which is the smallest value a UInt8 can hold
willUnderflow = willUnderflow &- 1
// willUnderflow is now equal to 255
2.3除零溢出 (&/)
let x = 1
let y = x / 0
let x = 1
let y = x &/ 0
// y is equal to 0
3.优先级和结合性
运算符的优先级是的一些运算符优先与其他运算符,高优先级的运算符会先计算2 + 3 * 4 % 5
// this equals 4
2 + ((3 * 4) % 5)
4.运算符函数
让已有的运算符也可以对自定义的类和结构体进行运算,称为运算符重载在func之前写上属性 @infix 即可定义一个全局的 + 函数
// 参数命名为left 和 right 表示 + 左边和有右边的对象
struct Vector2D {
var x = 0.0, y = 0.0
}
@infix func + (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y + right.y)
}
let vector = Vector2D(x: 3.0, y: 1.0)
let anotherVector = Vector2D(x: 2.0, y: 4.0)
let combinedVector = vector + anotherVector
// combinedVector is a Vector2D instance with values of (5.0, 5.0)
4.1前置和后置运算符
实现前置后者后置运算符,在定义该运算符的时候与关键字之前标注 @prefix 或 @postfix 属性@prefix func - (vector: Vector2D) -> Vector2D {
return Vector2D(x: -vector.x, y: -vector.y)
}
let positive = Vector2D(x: 3.0, y: 4.0)
let negative = -positive
// negative is a Vector2D instance with values of (-3.0, -4.0)
let alsoPositive = -negative
// alsoPositive is a Vector2D instance with values of (3.0, 4.0)
4.2组合赋值运算符
组合赋值是其他运算符和赋值运算符一起执行的运算,如 += 把加运算和赋值运算符组合成一个操作,实现一个组合赋值符号需要用 @assignment 属性,还要把运算符的左参数设置成inout, 因为这个参数会在运算符函数内修改这个值@assignment func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
var original = Vector2D(x: 1.0, y: 2.0)
let vectorToAdd = Vector2D(x: 3.0, y: 4.0)
original += vectorToAdd
// original now has values of (4.0, 6.0)
// 以下把 @assignment和 @prefix 或 @postfix属性结合起来
@prefix @assignment func ++ (inout vector: Vector2D) -> Vector2D {
vector += Vector2D(x: 1.0, y: 1.0)
return vector
}
var toIncrement = Vector2D(x: 3.0, y: 4.0)
let afterIncrement = ++toIncrement
// toIncrement now has values of (4.0, 5.0)
// afterIncrement also has values of (4.0, 5.0)
4.3比较运算符
@infix func == (left: Vector2D, right: Vector2D) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
@infix func != (left: Vector2D, right: Vector2D) -> Bool {
return !(left == right)
}
let twoThree = Vector2D(x: 2.0, y: 3.0)
let anotherTwoThree = Vector2D(x: 2.0, y: 3.0)
if twoThree == anotherTwoThree {
println("These two vectors are equivalent.")
}
// prints "These two vectors are equivalent."
5.自定义运算符
自定义的运算符只能使用以下字符 : / = - + * % < > ! & | ^ 。~新的运算符声明需要在全局使用operator关键字声明,可以声明为前置,中置或后置
operator prefix +++ {}
定义一个新的前置运算符 +++
@prefix @assignment func +++ (inout vector: Vector2D) -> Vector2D {
vector += vector
return vector
}
var toBeDoubled = Vector2D(x: 1.0, y: 4.0)
let afterDoubling = +++toBeDoubled
// toBeDoubled now has values of (2.0, 8.0)
// afterDoubling also has values of (2.0, 8.0)
5.1自定义中置运算符的优先级和结合性
可为自定义的中置运算符指定优先级和结合性,结合性可取值的范围有left,right和none,左结合运算符跟其他优先级相同的左结合写在一起时,会跟左边的操作数结合,同理,右结合运算符会跟右边的操作数结合,非结合运算符不能跟其他相同优先级的运算符写在一起operator infix +- { associativity left precedence 140 }
func +- (left: Vector2D, right: Vector2D) -> Vector2D {
return Vector2D(x: left.x + right.x, y: left.y - right.y)
}
let firstVector = Vector2D(x: 1.0, y: 2.0)
let secondVector = Vector2D(x: 3.0, y: 4.0)
let plusMinusVector = firstVector +- secondVector
// plusMinusVector is a Vector2D instance with values of (4.0, -2.0)