我使用 Decimal 和 Double 进行了一系列计算。如果没有泛型,就会有很多重复的代码。有些地方我最终需要更原生格式的十进制,但我似乎不知道如何在 Swift 中做到这一点。
一个假设的例子:Decimal中没有log2(),但由于可接受的误差范围,我想将其转换为Double并以这种方式使用它。
最初我以为我只是创建一个适用于 Double 和 Decimal
的通用函数// Dtype is either Decimal or Double
typealias Dtype = SignedNumeric
func mylog2<T: Dtype>(_ x: T) -> Double
{
let x_double: Double = Double(truncating: x as NSNumber) //'T' is not convertible to 'NSNumber'
return log2(x_double)
}
但是我得到了一个错误,所以我想我只需将它们分成离散函数即可。经过思考,我认为 T 无法暴露其实际类型。然后我想我应该将函数拆分为离散类型并尝试以这种方式使用它:
func mylog2(_ x: Decimal) -> Double
{
let x_double: Double = Double(truncating: x as NSNumber)
return log2(x_double)
}
func mylog2(_ x: Double) -> Double
{
return log2(x)
}
但是我不知道如何让 T 通过离散类型使用 mylog2() 函数:
func myExample<T: Dtype>(_ a: T, _ b: T) -> Double
{
let c: T = (a + b) * (b - a)
//bunch of other maths funcs
return mylog2(c) //No exact matches in call to global function 'mylog2'
}
我很确定在其他语言中也有办法处理这样的情况,所以一定有办法。我可能用不正确的 Swift 思维方式来解决这个问题,并且有一种完全不同的方式,我不知道如何做到这一点。无论如何,如果有人可以帮助我快速解决这个问题,我将不胜感激。
只需声明您自己的协议,需要实现
log2
方法。 Double
和 Decimal
均符合此协议。
protocol Log2 {
func log2() -> Double
}
extension Decimal: Log2 {
func log2() -> Double {
Darwin.log2(Double(truncating: self as NSNumber))
}
}
extension Double: Log2 {
func log2() -> Double {
Darwin.log2(self)
}
}
然后您可以将泛型类型参数约束为
Log2 & SignedNumeric
。
typealias Dtype = SignedNumeric & Log2
func myExample<T: Dtype>(_ a: T, _ b: T) -> Double
{
let c: T = (a + b) * (b - a)
//bunch of other maths funcs
return c.log2()
}