当前位置: 代码迷 >> 综合 >> Day08:位运算
  详细解决方案

Day08:位运算

热度:57   发布时间:2023-09-29 19:14:14.0
  • 位取反运算
  1. 位取反运算符(~)是对所有位的数字进行取反操作。
  • 位与运算符
  1. 位与运算符(&)可以对两个数的比特位进行合并。它会返回一个新的数,只用当这两个数都是1的时候才返回1。
  • 位或运算符
  1. 位或运算符(!)可以对两个比特位进行比较,然后返回一个新的数,只要两个操作位任意一个为1时。那么对应的位数就为1。
  • 位异或运算符
  1. 位异或运算符,或者说“互斥或”(^)可以对两个数的比特位进行比较。它返回一个新的数,当两个操作数的对应位不相同时,该数的对应位就为1。
  • 位左移和右移运算符。
  1. 位左移运算符(《)和右移运算符(》)可以把所有位数的数字向左或者向右移动一个确定的位数。
  2. 位左移和右移具有给整数乘以或除以二的效果。将一个数移一位相当于把这个数翻倍,讲一个数右移一位相当于把这数减半。
  • 无符号整数的移位操作
  1. 已经存在的比特位按指定的位数进行左移和右移。
  2. 任何移动超出整型存储边界的位都会被丢弃。
  3. 用0来填充向左或向右移动产生的空白位。
  • 有符号整数的位操作
  1. 有符号整数使用它的第一位(所谓的符号位)来表示这个整数是正数还是负数。符号位为0表示正数,1表示为负数。
  2. 其余的位数(所谓的数值位)存储了实际的值。有符号正整数和无符号数的存储方式是一样的,都是从0开始算起。
  3. 但是负数的存储方式略有不同。它存储的是2的n次方减去它的绝对值,这里的n为数值的位数。
  • 补码表示的优点
  1. 首先,如果想给-4加个-1,只需要将这两个数的全部八个比特位相加(包括符号位),并且将计算结果中超出的部分丢弃。其次,使用二进制补码可以使负数的位左移和右移操作得到跟整数同样的效果,即每向左移一位就将自身的数乘以2,每向右移动一位就将自身的数除以2.要到达到此目的,对有符号整数的右移有一个额外的规则:当对整数进行位右移操作时,遵守与无符号整数相同的规则,但是对于位移产生的空白位使用符号位进行填充,而不是0。
  • 【代码演示】
    ///1、取反
    let number1:UInt8 = 255
    let number2 = ~number1
    print(number2)//结果:0///2、与
    let number3 = number1 & number2
    print(number3)//结果:0
    let number4 = number1 | number2
    print(number4)//结果:255///3、异或
    let number5 = number1 ^ number2
    print(number5)//结果:255///4、左移 右移
    let number6:Int8 = 8
    print(number6 << 1) //结果:16
    print(number6 >> 1) //结果:4

  • 运算符优先级和结合性
  1. 运算符的优先级使得一些运算符优先于其他运算符,高优先级的运算符会先被计算。
  2. 结合性定义了具有相同优先级的运算符的是如何结合(或关联)的一一是与左边结合为一组,还是与右边为一组。可以这样理解:“它们是与左边的表达式结合的“或者”它们是与右边的表达式结合的。
  • 运算符优先级-显示括号
  1. 2 + 3 % 4*5 等价于 2+((3%4)*5)
  2. swift语言中逻辑运算符&&和||是左关联的,这意味着多个逻辑运算符组合表达式会先计算最左边的子表达式。
  • 运算符重载
  1. 类和结构体可以为现有的运算符提供自定义的实现,称为运算符重载。
  • 一元运算符重载
  1. 类和结构体也能提供标准一元运算符的实现。
  • 组合赋值运算符重载
  1. 组合赋值运算符将赋值运算符(=)与其他运算符进行结合。
  2. 在实现的时候,需要把运算符的左参数设置成inout类型,因为这个参数的值会在运算符内直接被修改。
  • 等价运算符重载
  1. 自定义类和结构体不接受等价运算符的默认实现,也就是所谓的“等价”运算符(==)和“不等于”运算符(!=)。
  • swift为以下自定义类型提供等价运算符合成实现
  1. 只拥有遵循Equatable协议存储属性的结构体。
  2. 只拥有遵循Equatable协议关联类型的枚举。
  3. 没有关联的枚举。
  • 【代码演示】
    //1、常规运算符重载
    /** 错误案例
    struct Vector2D {var x = 0.0,y = 0.0
    }let vector = Vector2D(x: 1.0, y: 2.0)
    let anotherVector = Vector2D(x: 3.0, y: 4.0)let thiedVector = vector + anotherVector//不可直接相加会保存*/struct Vector2D {var x = 0.0,y = 0.0
    }extension Vector2D {static func + (left: Vector2D,right:Vector2D) -> Vector2D {return Vector2D(x: left.x + right.x, y: left.y + right.y)}
    }let vector = Vector2D(x: 1.0, y: 2.0)
    let anotherVector = Vector2D(x: 3.0, y: 4.0)
    let thiedVector = vector + anotherVector//可直接相加会保存print("x is \(thiedVector.x), y is \(thiedVector.y)")//结果:x is 4.0, y is 6.0//2、一元运算符重载extension Vector2D {static prefix func - (vector:Vector2D) -> Vector2D{return Vector2D(x: -vector.x, y: -vector.y)}}let vector2 = -vector
    print("x is \(vector2.x),y is \(vector2.y)")//结果:x is -1.0,y is -2.0//3、组合运算符重载extension Vector2D {static func += (left: inout Vector2D,right:Vector2D) {left = Vector2D(x: left.x + right.x, y: left.y + right.y)}
    }var vector3 = Vector2D(x: 1.0, y: 1.0)
    let vector4 = Vector2D(x: 2.0, y: 3.0)vector3 += vector4
    print("x is \(vector3.x),y is \(vector3.y)")//结果:x is 3.0,y is 4.0//4、等价运算符重载var vector5 = Vector2D(x: 1.0, y: 2.0)
    let vector6 = Vector2D(x: 1.0, y: 2.0)extension Vector2D:Equatable{static func == (left:Vector2D,right:Vector2D) ->Bool {return (left.x == right.x) && (left.y == right.y)}
    }print(vector5 == vector6) //结果:true
    

  • 自定义运算符
  1. 除了实现标准运算符,在swift当中还可以声明和实现自定义运算符(custom operators)。
  2. 新的运算符要在全局作用域内,使用operator关键字进行声明,同时还要指定prefix,infix或者postfix限定符。
  • 自定义中缀运算符的优先级和结合性。
  1. 自定义的中缀(infix)运算符也可以指定优先级和结合性。
  • 【代码演示】
//5、自定义一元运算符
prefix operator +++
extension Vector2D {static prefix func +++(vector:Vector2D) -> Vector2D{return Vector2D(x: vector.x + vector.x , y:  vector.y +  vector.y)}
}let vectorDouble = Vector2D(x: 2, y: 3)
let doubleVector = +++vectorDouble
print("doubleVector.x is \(doubleVector.x),doubleVector.y is \(doubleVector.y)")//结果:doubleVector.x is 4.0,doubleVector.y is 6.0
//6、自定义中缀运算符infix operator +-:AdditionPrecedence
extension Vector2D{static func +-(left:Vector2D,right:Vector2D) ->Vector2D{return Vector2D(x: left.x + right.x, y: left.y - right.y)}
}let firstVector = Vector2D(x: 3, y: 4)
let secondVector = Vector2D(x: 6, y: 7)
let fourVector = firstVector +- secondVectorprint("fourVector.x is \(fourVector.x),fourVector.y is \(fourVector.y)")//结果:fourVector.x is 9.0,doubleVector.y is -3.0infix operator *^:MultiplicationPrecedenceextension Vector2D{static func *^(left:Vector2D,right:Vector2D) -> Vector2D{return Vector2D(x: left.x * right.x, y: left.y * left.y + right.y * right.y)
}
}let sevenVector = Vector2D(x: 3, y: 5)
let eightVector = Vector2D(x: 2, y: 4)
let nineVector = sevenVector *^ eightVectorprint("nineVector.x is \(nineVector.x),nineVector.y is \(nineVector.y)")//结果:nineVector.x is 6.0,doubleVector.y is 39.0//7、优先级组struct coordinate2D{var x = 0.0,y = 0.0
}infix operator +-:AdditionPrecedence
extension coordinate2D{static func +-(left:coordinate2D,right:coordinate2D) ->coordinate2D{return coordinate2D(x: left.x + right.x, y: left.y - right.y)}
}infix operator *^:MyPrecedence
//指定组
precedencegroup MyPrecedence {associativity:leftlowerThan:AdditionPrecedence
}extension coordinate2D{static func *^(left:coordinate2D,right:coordinate2D) -> coordinate2D{return coordinate2D(x: left.x * right.x, y: right.y * right.y + left.y * left.y)}
}let firstcoordinate2D = coordinate2D(x: 1, y: 2)
let seconfcoordinate2D = coordinate2D(x: 2, y: 4)
let thirdcoordinate2D = coordinate2D(x: 3, y: 5)let resultcoordinate2D = firstcoordinate2D +- seconfcoordinate2D *^ thirdcoordinate2Dprint("resultcoordinate2D.x is \(resultcoordinate2D.x),resultcoordinate2D.y is \(resultcoordinate2D.y)")//结果:resultcoordinate2D.x is 9.0,resultcoordinate2D.y is 29.0