我想使用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中编写这个函数?
答案 0 :(得分:1)
一个问题是FloatingPoint
不是ExpressibleByFloatLiteral
的子协议,因此您的浮点文字不一定能转换为T
。您可以通过将FloatingPoint
更改为BinaryFloatingPoint
(这是ExpressibleByFloatLiteral
的子协议)或将ExpressibleByFloatLiteral
添加为单独的要求来解决此问题。
然后,您将遇到以下问题:pow
函数不是FloatingPoint
的通用函数,而是FloatingPoint
或BinaryFloatingPoint
的成员执行取幂。您可以通过创建新协议并使现有的浮点类型符合它来解决此问题:
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)))
}