大概内容
递归,异常,索引,断言
递归
//求C(m,n)函数m!/n!/(m-n)! = m!/(n!*(m-n)!)或者n*(n-1)!
func Cmn(m:Int, _ n:Int) ->Int{
assert(m >= n,"m必须大于等于n")//断言,m小于n时提示用户"m必须大于等于n"
return Int(a3(m) / a3(n) / a3(m - n))
}
/*
//n*(n-1)! 采用递归方法,效率没有采用循环的效率高
func f(n:Int) -> Double{
if n == 0 || n == 1{
return 1
} //收敛
return Double(n) * f(n - 1)//条件
}
//函数递归调用(一个函数直接或者间接的调用自身),采用递归方法,效率没有采用循环的效率高,能用循环写出的就用循环,很麻烦很复杂的问题可以采用递归
//使用递归必须要有
//1.递归公式
//2.收敛条件
*/
//用递归计算1-n的和
func sum(n:Int) -> Int{
if n == 1{
return 1
}
return n + sum(n - 1)
}
异常
Fraction 分数类
//x和y的最大公约数跟y%x的最大公约数是一样的(欧几里得算法)
//求最大公约数
func gcd(x:Int, _ y:Int) ->Int{
if x > y{
return gcd(y, x)
}
else if y % x != 0{
return gcd(y % x, x)
}
else {
return x
}
}
//定义一个遵循ErrorType协议的枚举
//通过不同的case定义程序中可能出现的若干异常状况
/**
- ZeroDenominator:分母为0
- DividByZero:除数为0
*/
enum FractionError:ErrorType{
case ZeroDenominator,DividByZero
}
class Fraction{
private var _num:Int //分子
private var _den:Int //分母
// 如果一个方法抛出了异常,那么在声明方法时必须写上throws关键字
init(num:Int,den:Int) throws {
_num = num
_den = den
// 如果程序中出现问题就抛出异常
// 被throw关键字抛出的必须遵循ErrorType协议
if _den == 0{
throw FractionError.ZeroDenominator
}
else{
normoalize()
simplify()
}
}
var info:String{
get {
return _num == 0 || _den == 1 ? "\(_num)" : "\(_num)/\(_den)"
}
}
func add(other:Fraction) throws -> Fraction{
return try Fraction(num: _num * other._den + other._num * _den, den: _den * other._den)
}
func sub(other:Fraction) throws ->Fraction{
return try Fraction(num: _num * other._den - other._num * _den, den: _den * other._den)
}
func mul(other:Fraction) throws ->Fraction{
return try Fraction(num: _num * other._num, den: _den * other._den)
}
func div(other:Fraction) throws ->Fraction{
if other._num == 0{
throw FractionError.DividByZero
}
return try! Fraction(num: _num * other._den, den: _den * other._num)
}
func normoalize() ->Fraction{
if _den < 0{
_num = -_num
_den = -_den
}
return self
}
func simplify() ->Fraction{
if _num == 0{
_den = 1
}
else{
let x = abs(_num)
let y = abs(_den)
let g = gcd(x, y)
_num /= g
_den /= g
}
return self //返回本身的分数对象
}
}
//运算符重载 (为自定义的类型定义运算符)
func +(one:Fraction,two:Fraction) -> Fraction{
// 如果能够保证方法调用时不出现异常那么可以在try后面加!
// 这样就可以在不写do...catch的情况下调用可能出状况的方法
return try! one.add(two)
}
func -(one:Fraction,two:Fraction) -> Fraction{
return try! one.sub(two)
}
func *(one:Fraction,two:Fraction) -> Fraction{
return try! one.mul(two)
}
func /(one:Fraction,two:Fraction) throws -> Fraction{
return try one.div(two)
}
测试
//对于可能出状况的代码要放到do...catch语句中
//在可能出状况的代码前面还要加上try,表示尝试执行
//如果在do中的代码没有出任何状况那么catch就不会执行
//如果do中出现状况,代码就不会继续往下执行,而是转移到catch中
//在do的后面可以跟上多个catch用于捕获不同的状况,但是最多只有一个catch会被执行
do {
let f1 = try Fraction(num: 3, den: 0)
let f2 = try Fraction(num: 0, den: 5)
let f3 = f1 + f2
print(f3.info)
let f4 = f1 - f2
print(f4.info)
let f5 = f1 * f2
print(f5.info)
let f6 = try f1 / f2
print(f6.info)
}
catch FractionError.ZeroDenominator{
print("分母不能为0")
}
catch FractionError.DividByZero{
print("除数不能为0")
}
catch{
print("出错了,我也不知道什么问题")
}
//不想写do...catch时也可以写成下面的代码
func foo(){
// 如果能保证代码不出错可以在try后面加!
// 如果不能保证代码是否会出错可以在代码后面加?
// 需要注意的是由?的地方会产生optional
// 稍后可能还需要对可空类型进行拆封且方式有二:
// 1.不安全的做法:xxx!
// 2.安全的做法:有if let = xxx
let f1 = try? Fraction(num: 3, den: 0)
let f2 = try? Fraction(num: 0, den: 5)
// let c = f1! + f2! //不安全
// 安全
if let a = f1, b = f2{
let c = a + b
print(c.info)
}
else{
print("无效的分数不能运算")
}
}
索引
例子1
片段代码,详细参考gobangApp改进版
//建立索引****
subscript(row:Int,col:Int) -> Bool{
get{ return board[row][col] == .Space }
set(isBlack){
if board[row][col] == .Space{
board[row][col] = isBlack ? .Black : .White
isBlackTurn = !isBlackTurn
}
}
}
测试
if board[row,col]{
board[row,col] = board.isBlackTurn
setNeedsDisplay()
}
例子2:生成随机验证码
func randomNum(min:Int,_ max:Int) -> Int{
return Int(arc4random_uniform(UInt32(max - min)) + 1) + min
}
//扩展原生API
extension String{
var lenth: UInt32 {
get{ return UInt32(self.characters.count) }
}
//建立索引
subscript(index:Int) -> Character{
get { return self[self.startIndex.advancedBy(index)] }
}
}
func generate(lenth:Int) ->String{
var code = ""
if lenth > 0{
let str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
for _ in 0..<lenth - 1{
code.append(str[randomNum(0, str.characters.count)])
}
}
return code
}
print(generate(5))
断言
当需要判断是否满足某个条件时可以使用断言assert,满足条件程序继续执行,不满足就提示逗号后面的内容。
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")
// this causes the assertion to trigger, because age is not >= 0
网友评论