具有通用类型约束的数值型最优自定义算子

时间:2016-12-15 06:11:21

标签: swift generics swift3

我正在实施(一篇文章)两个自定义中缀运算符:

  • ¿% - 计算总数的百分比。
  • %? - 计算代表总分段的百分比。

在调试了一些错误并查找信息后,我终于找到了让代码正常工作的方法:

protocol NumericType {
    static func *(lhs: Self, rhs: Self) -> Self
    static func *(lhs: Self, rhs: Int) -> Self
    static func /(lhs: Self, rhs: Self) -> Self
    static func /(lhs: Self, rhs: Int) -> Self
} // NumericType

extension Double : NumericType {
    internal static func *(lhs: Double, rhs: Int) -> Double {
        return lhs * Double(rhs)
    }

    internal static func /(lhs: Double, rhs: Int) -> Double {
        return lhs / Double(rhs)
    }
 }

extension Float  : NumericType {
    internal static func *(lhs: Float, rhs: Int) -> Float {
        return lhs * Float(rhs)
    }

    internal static func /(lhs: Float, rhs: Int) -> Float {
        return lhs / Float(rhs)
    }
 }

extension Int : NumericType { }

infix operator ¿%

func ¿% <T: NumericType>(percentage: T, ofThisTotalValue: T) -> T {

    return (percentage * ofThisTotalValue) / 100

} // infix operator ¿%

infix operator %?

func %? <T: NumericType>(segmentOf: T, thisTotalValue: T) -> T {

    return (segmentOf * 100) / thisTotalValue

} // infix operator %?

let percentage: Double = 8
let price: Double = 45

let save = percentage ¿% price

print("\(percentage) % of \(price) $ = \(save) $")

print("\(save) $ of \(price) $ = \(save %? price) %")

......输出:

8.0 % of 45.0 $ = 3.6 $
3.6 $ of 45.0 $ = 8.0 %

我的问题如下:

您认为可能有更优化和可读的方法吗?

是?你能给出一些建议或分享一个例子吗?

1 个答案:

答案 0 :(得分:1)

首先,我对使用自定义运算符持怀疑态度。 个人我只是有一个执行此计算的函数:

func percent(of partial: Double, from amount: Double) -> Double {
    return partial / amount * 100
}

percent(of: 50, from: 100)
// -> 50

对于可读性和可维护性,我觉得在长期(和短期)方面会更容易。

话虽如此......如果你真的想在这里创建这些自定义操作符,那么我将如何处理它。

你走在正确的道路上!你会得到错误:

  

二元运算符&#39; *&#39;不能应用于类型&#39; NumericType&#39;的操作数。和&#39; Double&#39;

您沿着实现函数的道路前进,以便*和/运算符可用于类型NumericTypeDouble

但实际上,不是重新定义*和/的签名来处理新类型,而是更容易找到从泛型类型中获取double值并在计算中使用它的方法

以下是它的外观:

protocol NumericType {
    var doubleValue: Double { get }
}

infix operator ¿%
infix operator %?

func ¿% <T: NumericType>(percentage: T, ofTotal: Double) -> Double {
    return percentage.doubleValue * ofTotal / 100.0
}

func %? <T: NumericType>(segment: T, ofTotal: Double) -> Double {
    return segment.doubleValue * 100 / ofTotal
}

extension Double: NumericType {
    var doubleValue: Double { return self }
}

extension Int: NumericType {
    var doubleValue: Double { return Double(self) }
}

希望这会有所帮助,请请重新考虑使用标准功能而不是这些自定义操作员!