Swift 高级运算符(二十)

高级运算符


1.位运算符

1.1按位取反

前置运算符 ~ 对一个操作数的每一位都取反,后紧跟操作数,不加空格
let initialBits: UInt8 = 0b00001111
let invertedBits = ~initialBits  // equals 11110000

1.2按位与

对两个数进行操作,返回一个新的数,两个数的同一位都为1时,输出数才为1
let firstSixBits: UInt8 = 0b11111100
let lastSixBits: UInt8  = 0b00111111
let middleFourBits = firstSixBits & lastSixBits  // equals 00111100

1.3按位或

比较两个数,返回一个新的数,两个数的同一位都不为0时,输出数才为1
let someBits: UInt8 = 0b10110010
let moreBits: UInt8 = 0b01011110
let combinedbits = someBits | moreBits  // equals 11111110

1.4按位异或

比较两个数返回一个新的数,两个数的同一位不同时,输出数才为1,相同输出0
let firstBits: UInt8 = 0b00010100
let otherBits: UInt8 = 0b00000101
let outputBits = firstBits ^ otherBits  // equals 00010001

1.5按位左移/右移

把一个数的比特位按定义的规则向左或向右移动指定的位数,相当于把一个整数乘以或除以一个因子为2的整数,左移相当于乘以2,右移相当于除以2
1.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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值