簡而言之
當高精度很重要時,我正在玩計算來分析不同數字型別的可靠性和錯誤傳播。將相同的公式應用于不同的數字型別,我嘗試使用泛型但無法涵蓋Decimal型別。
有沒有辦法有一個單一的通用實作覆寫Float,Double以及Decimal簡單的數字函式?
更多細節
計算基于穆勒序列,遞回地應用一個非常簡單的公式。三種考慮型別的代碼是:
func mullerFormulaDouble(y:Double, z:Double ) -> Double {
return 108.0 - ( (815.0-1500.0/z)/y)
}
func mullerFormulaFloat(y:Float, z:Float ) -> Float {
return 108.0 - ( (815.0-1500.0/z)/y)
}
func mullerFormulaDecimal(y:Decimal, z:Decimal ) -> Decimal {
return Decimal(108) - ( (Decimal(815)-Decimal(1500)/z)/y)
}
通用計算如下所示:
func mullerFormula<T>(y:T, z:T ) -> T { // a constraint is required for T
let a = T(1500)/z
let b = (T(815) - a)/y
return T(108) - b
}
print (mullerFormula(y:4.0, z:4.24))
print (mullerFormula(y:Float(4.0), z:Float(4.24)))
print (mullerFormula(y:Decimal(4), z:Decimal(sign:.plus, exponent: -2, significand:424)))
由于沒有初始化程式的錯誤訊息,上面的代碼沒有編譯,T這是有道理的。需要一些型別約束才能使其作業。所以我使用T:Numeric了 ,但它在除法上失敗了,錯誤是它不能應用于運算元T?和T.
后來出現了幾個錯誤,我最終得到了T:FloatingPoint. 然后它適用于Doubleand Float,但我仍然不能使用它Decimal,因為Decimal不符合FloatingPoint. 我沒有為我的型別約束找到任何其他合適的通用協議。
考慮到所有這三種數字型別都支持從整數初始化和四種基本操作,我無法想象沒有辦法撰寫一個通用函式來涵蓋所有這些。因此我的問題。
uj5u.com熱心網友回復:
方法一:定義一個BasicNumeric包含你需要的功能的協議
這是一種方法。創建一個具有您要使用的型別的公共屬性的protocol呼叫。BasicNumeric宣告您的型別實作了該協議,并使用該協議作為新函式中的約束:
protocol BasicNumeric: ExpressibleByIntegerLiteral {
static func (_: Self, _: Self) -> Self
static func -(_: Self, _: Self) -> Self
static func *(_: Self, _: Self) -> Self
static func /(_: Self, _: Self) -> Self
}
extension Double: BasicNumeric { }
extension Float: BasicNumeric { }
extension Decimal: BasicNumeric { }
func mullerFormula<T: BasicNumeric>(y:T, z:T ) -> T {
let a = 1500/z
let b = (815 - a)/y
return 108 - b
}
print (mullerFormula(y:4.0, z:4.24))
print (mullerFormula(y:Float(4.0), z:Float(4.24)))
print (mullerFormula(y:Decimal(4), z:Decimal(sign:.plus, exponent: -2, significand:424)))
輸出:
-7.306603773584911
-7.3066025
-7.30660377358490566037735849056603775
方法二:定義Divisible協議并使用Numeric協議
Leo Dabus 在評論中提供了這種替代實作。
protocol Divisible {
static func /(_: Self, _: Self) -> Self
}
extension Double: Divisible { }
extension Float: Divisible { }
extension Decimal: Divisible { }
func mullerFormula<T: Numeric & Divisible>(y: T, z: T) -> T {
let a = 1500 / z
let b = (815 - a) / y
return 108 - b
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/492861.html
上一篇:SeleniumWebDriverManager-在Linux服務器上運行時出現例外
下一篇:資料在熊貓中被覆寫
