如何使我的求幂运算符适用于Swift中的所有数字类型?

如何使我的求幂运算符适用于Swift中的所有数字类型?,swift,operators,Swift,Operators,我已在Swift中创建了^^运算符。如何使它像所有其他运算符一样处理整数和double 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 } 中缀运算符^^{

我已在Swift中创建了^^运算符。如何使它像所有其他运算符一样处理整数和double

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
}
中缀运算符^^{}
func^^(数字:Int,幂:Int)->Int{
var结果=功率>0?编号:0

如果power>1{for x in 1..这里有一个更安全的实现,使用操作符重载。对于整数类型, 您可以将
^^
定义为

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
}
并使
Float
Double
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))
}

Swift 4的更新:

IntegerType
已成为
BinaryInteger
(),并且 声明运算符的语法已更改 ()

这是一个适用于所有整数和浮点的实现 带
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))
}

关于Swift 4中引入的新协议层次结构。

您必须尝试此pow(num,2)是的,但如果您想将值平方,则此值非常有用。是的,此值非常有用!可能重复@LeonardoSavioDabus:您现在遇到了混合问题,(您的)解决方案和分析都在问题中。特别是你的原始问题不再可见,这使得我的答案(试图回答你的原始问题)毫无用处。如果你的问题中的所有代码都是类型安全的,未来的读者不会理解为什么A写了一个“更类型安全的版本”(事实上是根据我在回答中的建议).-我建议您将问题还原为原始版本,并将您的解决方案放入答案中。@LeonardoSavioDabus:问题是,
square*=square
即使在最后一步中也进行了计算,不再需要该值。这会导致溢出。我已修改了代码,它现在可以工作到
Int64(2)^^62和UInt64(2)^^63
@LeonardoSavioDabus:正如您已经注意到的,这种方法并不比您的方法快,因为指数最多限制为63。在处理大指数时,它的优势变得更加明显。@LeoDabus:Updated。使用
T:Numeric
可以自动覆盖浮点或十进制的情况!@LeoDabus:再次更新:)–我已将指数限制为类型
Int
,但现在它正确地适用于所有基类型(整数、浮点、十进制)。我认为这是一个合理的折衷方案。(如果
pow()
是泛型的,它可以简化,但不是。)@LeoDabus:的确如此!我还删除了以十进制为基数的版本,该版本不适用于负指数(返回NaN)。
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
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