溢出运算符
溢出加法&+ 溢出减法&- 溢出乘法&*
对于无符号与有符号整型数值来说,当出现上溢时,它们会从数值所能容纳的最大数变成最小的
数。同样的,当发生下溢时,它们会从所能容纳的最小数变成最大的数。
合并空值运算符
(a ??b)
• 合并空值运算符( a ?? b )如果可选项 a 有值则展开,如果没有值,是 nil ,则返
回默认值 b 。
• 表达式 a 必须是一个可选类型。表达式 b 必须与 a 的储存类型相同。
区间运算符
- (a...b) = a到b包含b
- (a..<b) = a到b不包含b
- (a...) = a开始到结束
- (...a) = 开始到a
- 通过 reversed() 方法,我们可以将一个正序循环变成逆序循环。
for i in (0..<10),reversed(){
print(i)
}
9 8 7 6 5 4 3 2 1 0
- 区间运算符可以作用在 Comparable 类型上,返回闭区间和半闭区间。
let welcome = "hello,world"
let interval = "a"..."z"
for c in welcome {
if !interval.contains(String(c){
print("\(c)不是字母")
}
}
,不是字母
位运算符
- ~ 对所有位的数字取反操作
0 0 0 0 1 1 1 1
~
=
1 1 1 1 0 0 0 0
- & 与操作有1为1,有0为0
1 1 1 1 1 1 0 0
&
0 0 1 1 1 0 1 1
=
0 0 1 1 1 0 0 0
- | 位或操作,两个操作位任意一个为1时,操作后为1
1 1 0 0 1 1 0 0
|
0 1 1 1 1 1 0 0
=
1 1 1 1 1 1 0 0
- ^ 位异或操作,不同时为1
1 0 1 1 0 0 0 1
^
0 0 1 1 1 0 0 1
=
1 0 0 0 1 0 0 0
位左移和右移运算符
- (<<) 左移动=乘以2的效果
- (>>) 右移动=除以2的效果
00110011<<2 = 11001100
有符号整数的移位操作
• 有符号整数使用它的第一位(所谓的符号位)来表示这个整数是正数还是负数。符号位为 0 表示为正
数,1 表示为负数。
• 其余的位数(所谓的数值位)存储了实际的值。有符号正整数和无符号数的存储方式是一样的,都是
从 0 开始算起。
• 但是负数的存储方式略有不同。它存储的是 2 的 n 次方减去它的绝对值,这里的 n 为数值位的位
数。
1 1111100 = -4
交换数字
- 基本方法
var a = 10
var b = 8
var c = 0
c = a
a = b
b = c
- 不借助临时变量,交换两个变量的值。
var a = 10
var b = 8
a = a^b
b = a^b
a = a^b
求无符号整数二进制中 1 的个数
func countOfOnes(num:UInt) -> UInt{
var count :UInt = 0
var temp = num
while (temp != 0){
count += 1
temp = (temp - 1)&temp
}
return count;
}
print( countOfOnes(num: 0x11110001))
5
func countOfOnes_(num:UInt) -> UInt{
var count:UInt = 0
var temp = num
while (temp != 0){
count += temp&1
temp = temp >> 1
}
return count
}
print( countOfOnes_(num: 0x11100001))
4
如何判断一个整数位为 2 的整数次幂
func isPowerOfTwo(num:UInt) ->Bool{
var temp = num
guard temp != 1 else{
return true
}
while temp != 1 {
guard temp%2 == 0 else{
return false
}
temp = temp/2
print(temp)
}
return true
}
isPowerOfTwo(num: 2)
func isPowerOfTwo_(num:UInt) ->Bool{
return num & (num - 1) == 0
}
isPowerOfTwo_(num: 5)
缺失的数字
• 很多成对出现的正整数保存在磁盘文件中,注意成对的数字不一定是相邻的,如 2, 3, 4,
3, 4, 2……,由于意外有一个数字消失了,如何尽快找到是哪个数字消失了?
import Darwin
func findLoseNum (nums:[UInt]) -> UInt{
var loseNum:UInt = 0
for num in nums {
loseNum = num ^ loseNum
print(loseNum)
print("num is \(num)")
}
return loseNum
}
print("loseNum is \(findLoseNum(nums: [1,2,3,4,3,2,1]))")
- 成对相等出现的数互异或得出的数一定是0无论顺序,若有其他单个或多个的不同的数得出的结果就是单个的数或者多个不同的数的异或。
• 如果有两个数字意外丢失了(丢失的不是相等的数字),该如何找到丢失的两个数字?
func findOnlyOneNum(nums:[UInt]) -> (UInt,UInt) {
var temp : UInt = 0
for num in nums {
temp ^= num
}
print("temp 的异或 \(temp)")
var flag : UInt = 1
while (flag & temp) == 0 {
flag = flag << 1
}
var num1 : UInt = 0
var num2 : UInt = 0
for num in nums {
if num & flag == 0 {
print("flag == 0 \(num)")
num1 ^= num
}else{
print("flag != 0 \(num)")
num2 ^= num
}
}
return (num1,num2)
}
print(findOnlyOneNum(nums: [1,2,3,10,15,1,2,3]))
• 数组中,只有一个数出现一次,剩下都出现三次,找出出现一次的数字。
func findTheOnlyNum(nums: [UInt]) -> UInt {
var sum: UInt = 0
var binaryArr: [UInt] = [0]
for i in 0..<32 {
for num in nums {
sum += (num >> i & 1)
}
binaryArr.insert(sum, at: i)
print(binaryArr)
sum = 0
}
var theOnlyNum: UInt = 0
for (index, value) in binaryArr.enumerated() {
print(index)
if (value % 3) != 0 {
theOnlyNum += 1 << index
}
}
return theOnlyNum
}
print(findTheOnlyNum(nums: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6]))
步骤:
先用按位与把每一位二进制位拿出来并相加存进数组中
再把数组中的数字都%3
用按位或把数组中的数字操作在result上
运算符重载
类和结构体可以为现有的运算符提供自定义的实现,称为运算符重载。
类与结构体也能提供标准一元运算符的实现。
要实现前缀或者后缀运算符,需要在声明运算符函数的时候在 func 关键字之前指定 prefix 或者 postfix 限定符。
组合赋值运算符将赋值运算符( = )与其它运算符进行结合。
在实现的时候,需要把运算符的左参数设置成 inout 类型,因为这个参数的值会在运算符函数内直接被修改。
自定义类和结构体不接收等价运算符的默认实现,也就是所谓的“等于”运算符( == )
和“不等于”运算符( != )。要使用等价运算符来检查你自己类型的等价,需要和其他中缀运算符一样提供一个“等
于”运算符,并且遵循标准库的 Equatable 协议