如何使我的幂运算符与Swift中的所有数字类型一起使用? [英] How do I make my exponentiation operator work with all numeric types in Swift?

查看:54
本文介绍了如何使我的幂运算符与Swift中的所有数字类型一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Swift中创建了一个^^运算符.与其他所有运算符一样,如何使它与Integers和Doubles一起使用?

I have created a ^^ operator in Swift. How do I make it work with Integers and Doubles like all other operators?

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
}

推荐答案

这是使用操作符重载的更类型安全的实现.对于整数类型, 您可以将^^定义为

Here is a more type-safe implementation, using operator overloading. For integer types, you can define ^^ as

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
}

(我选择了一种更有效的变体,称为通过重复平方和乘法求幂".)

(I have chosen a more efficient variant called "exponentiation by repeated squaring and multiplication".)

对于浮点类型,定义一个协议,该协议涵盖所有可以 从和转换为Double:

For floating point types, define a protocol the covers all types that can be converted from and to Double:

protocol DoubleConvertible {
    init(_ value: Double)
    var doubleValue : Double { get }
}

并使FloatDoubleCGFloat符合该协议:

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) }
}

现在浮点指数可以简单地定义为

Now the floating point exponentiation can simply be defined as

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-0077改进的运算符声明.)

IntegerType has become BinaryInteger (SE-0104 Protocol-oriented integers) and the syntax for declaring operators has changed (SE-0077 Improved operator declarations.)

这是所有整数和浮点数的实现 指数Int的底基:

Here is an implementation for all integer and floating point bases with Int exponents:

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

请参见 SE-0104面向协议整数 关于Swift 4中引入的新协议层次结构.

See SE-0104 Protocol-oriented integers about the new protocol hierarchy introduced in Swift 4.

这篇关于如何使我的幂运算符与Swift中的所有数字类型一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆