如何实现同时支持Float、Double与Decimal类型的通用泛型计算函数?
The core problem here is that Decimal doesn’t conform to the FloatingPoint protocol, while the Numeric protocol lacks division support. To handle all three types (Float, Double, Decimal) with a single generic function, you can create a custom protocol that defines exactly the operations your Muller sequence formula requires, then extend each target type to conform to it.
Step 1: Define a Custom Protocol
Create a protocol that includes integer initialization and the four arithmetic operations needed for your formula:
protocol NumericArithmetic { init(_ integer: Int) static func + (lhs: Self, rhs: Self) -> Self static func - (lhs: Self, rhs: Self) -> Self static func * (lhs: Self, rhs: Self) -> Self static func / (lhs: Self, rhs: Self) -> Self }
Step 2: Conform Target Types to the Protocol
Extend Float and Double first—this is trivial since they already implement all required methods out of the box:
extension Float: NumericArithmetic {} extension Double: NumericArithmetic {}
For Decimal, we need to explicitly map the protocol requirements to its existing arithmetic operations (Foundation provides overloaded operators for Decimal in Swift 5+):
extension Decimal: NumericArithmetic { static func + (lhs: Decimal, rhs: Decimal) -> Decimal { return lhs + rhs } static func - (lhs: Decimal, rhs: Decimal) -> Decimal { return lhs - rhs } static func * (lhs: Decimal, rhs: Decimal) -> Decimal { return lhs * rhs } static func / (lhs: Decimal, rhs: Decimal) -> Decimal { return lhs / rhs } }
Step 3: Write the Generic Function
Now use your custom protocol as the type constraint for the generic Muller formula function:
func mullerFormula<T: NumericArithmetic>(y: T, z: T) -> T { let a = T(1500) / z let b = (T(815) - a) / y return T(108) - b }
Test the Implementation
Verify it works across all three types:
// Double test print(mullerFormula(y: 4.0, z: 4.24)) // Float test print(mullerFormula(y: Float(4.0), z: Float(4.24))) // Decimal test print(mullerFormula(y: Decimal(4), z: Decimal(sign: .plus, exponent: -2, significand: 424)))
Why This Works
- The
NumericArithmeticprotocol captures exactly the behavior your formula needs, avoiding the limitations of Apple’s built-in protocols that excludeDecimal. - Extending each type to conform gives you a unified interface, allowing the generic function to work seamlessly with all three numeric types.
内容的提问来源于stack exchange,提问作者Christophe

