我在Swift中创建了一个^^运算符。与所有其他运算符一样,如何与Integers和Doubles一起使用?
infix operator ^^ { } func ^^ (number:Int, power: Int) -> Int { var result = power > 0 ? number : 0 if power > 1 { for x in 1..<power { result *= number } } return result }
这是一个使用操作符重载的类型安全的实现。对于整数类型,您可以定义^^为
^^
infix operator ^^ { associativity left precedence 170 } func ^^<T : IntegerType, U : IntegerType> (base: T, var power: U) -> T { if power < 0 { return 0 } var result : T = 1 var square : T = base if power > 0 { if power % 2 == 1 { result *= square } power /= 2 } while power > 0 { square *= square if power % 2 == 1 { result *= square } power /= 2 } return result }
(我选择了一种更有效的变体,称为“通过重复平方和乘法求幂”。)
对于浮点类型,定义一个协议,该协议涵盖可以从和转换为的所有类型Double:
Double
protocol DoubleConvertible { init(_ value: Double) var doubleValue : Double { get } }
并作出Float,Double并CGFloat符合该协议:
Float
CGFloat
extension Double : DoubleConvertible { var doubleValue : Double { return self } } extension Float : DoubleConvertible { var doubleValue : Double { return Double(self) } } extension CGFloat : DoubleConvertible { var doubleValue : Double { return Double(self) } }
现在,浮点指数可以简单地定义为
func ^^<T : DoubleConvertible, U:DoubleConvertible> (base: T, power: U) -> T { return T(pow(base.doubleValue, power.doubleValue)) }
例子:
let x1 = 2^^3 // Int let x2 = UInt64(2)^^3 // UInt64 let x3 = 2.0 ^^ 3 // Double let x4 = Float(2.0) ^^ 3 // Float let x5 = "a" ^^ "b" // Compiler error
Swift 4更新:
IntegerType已变为BinaryInteger(SE-0104面向协议的整数),并且声明了运算符的语法已更改(SE-0077改进了运算符声明)。
IntegerType
BinaryInteger
这是所有具有Int指数的整数和浮点基数的实现:
Int
precedencegroup ExponentiationPrecedence { associativity: right higherThan: MultiplicationPrecedence } infix operator ^^: ExponentiationPrecedence func ^^<T : BinaryInteger>(base: T, power: Int) -> T { if power < 0 { return 0 } var power = power var result: T = 1 var square = base if power > 0 { if power % 2 == 1 { result *= square } power /= 2 } while power > 0 { square *= square if power % 2 == 1 { result *= square } power /= 2 } return result } func ^^(base: Float, power: Int) -> Float { return pow(base, Float(power)) } func ^^(base: Double, power: Int) -> Double { return pow(base, Double(power)) } func ^^(base: CGFloat, power: Int) -> CGFloat { return pow(base, CGFloat(power)) }
let x1 = 2^^3 // Int let x2 = UInt64(2)^^3 // UInt64 let x3 = 2.0 ^^ -3 // Double let x4 = Float(2.0) ^^ 3 // Float // let x6 = "a" ^^ 5 // Compiler error
有关 Swift 4中引入的新协议层次结构,请参阅SE-0104面向协议的整数。