如何为Float / Double使用FloatingPoint泛型类型

时间:2018-02-13 04:24:20

标签: swift

我想使用Float和Double值使下面的函数工作:

TokenValidationParameters

Swift 4 Documentation说我需要的是func srgb2linear(_ S: Float) -> Float { if S <= 0.04045 { return S / 12.92 } else { return pow((S + 0.055) / 1.055, 2.4) } } 泛型,表示Float和Double类,如:

FloatingPoint

但是,当我尝试这样做时,它不会编译时出现以下错误:

func srgb2linear<T: FloatingPoint>(_ S: T) -> T

对于表示浮点数的泛型,这样的运算符是如何实现的呢?如果不是这样,我怎么能在Swift中编写这个函数?

2 个答案:

答案 0 :(得分:1)

一个问题是FloatingPoint不是ExpressibleByFloatLiteral的子协议,因此您的浮点文字不一定能转换为T。您可以通过将FloatingPoint更改为BinaryFloatingPoint(这是ExpressibleByFloatLiteral的子协议)或将ExpressibleByFloatLiteral添加为单独的要求来解决此问题。

然后,您将遇到以下问题:pow函数不是FloatingPoint的通用函数,而是FloatingPointBinaryFloatingPoint的成员执行取幂。您可以通过创建新协议并使现有的浮点类型符合它来解决此问题:

protocol Exponentiatable {
    func toPower(_ power: Self) -> Self
}

extension Float: Exponentiatable {
    func toPower(_ power: Float) -> Float { return pow(self, power) }
}

extension Double: Exponentiatable {
    func toPower(_ power: Double) -> Double { return pow(self, power) }
}

extension CGFloat: Exponentiatable {
    func toPower(_ power: CGFloat) -> CGFloat { return pow(self, power) }
}

请注意,还有Float80类型,但标准库不为其提供pow功能。

现在我们可以编写一个有效的泛型函数:

func srgb2linear<T: FloatingPoint>(_ S: T) -> T
    where T: ExpressibleByFloatLiteral, T: Exponentiatable
{
    if S <= 0.04045 {
        return S / 12.92
    } else {
        return ((S + 0.055) / 1.055).toPower(2.4)
    }
}

答案 1 :(得分:0)

您可以使用Double参数定义第二个:

func srgb2linear(_ S: Double) -> Double {
  if S <= 0.04045 {
    return S / 12.92
  } else {
    return pow((S + 0.055) / 1.055, 2.4)
  }
}

或者,如果Float&lt; - &gt;双重转换不是问题:

func srgb2linear(_ S: Double) -> Double {
  return Double(srgb2linear(Float(S)))
}