问题
I'm writing an extension to a FloatingPoint protocol. I want to cast it to a Double in any possible way.
extension FloatingPoint {
var toDouble: Double {
return Double(exactly: self) ?? 0 //compile error
}
}
I'd prefer not to tell what I'm trying to achieve so we can focus just on above problem. I'd prefer to hear that's impossible to do it this way instead of receiving a valid workaround for the bigger problem I'm trying to solve.
I tried to use different Double constructors but maybe I wasn't trying hard enough.
回答1:
The problem there is that you need to extend BinaryFloatingPoint
instead of FloatingPoint
protocol:
extension BinaryFloatingPoint {
// Creates a new instance from the given value if possible otherwise returns nil
var double: Double? { Double(exactly: self) }
// Creates a new instance from the given value, rounded to the closest possible representation.
var doubleValue: Double { .init(self) }
}
Playground testing
let cgFloat: CGFloat = .pi // 3.141592653589793
let exactlyDouble = cgFloat.double // 3.141592653589793
let closestDoubleValue = cgFloat.doubleValue // 3.141592653589793
You can also create generic methods to return any floating point type that conforms to the BinaryFloatingPoint
protocol:
extension BinaryFloatingPoint {
func floatingPoint<F: BinaryFloatingPoint>() -> F? { F(exactly: self) }
func floatingPointValue<F: BinaryFloatingPoint>() -> F { .init(self) }
}
Playground testing
let float80pi: Float80 = .pi // 3.1415926535897932385
let closestCGFloatPiValue: CGFloat = float80pi.floatingPointValue() // 3.141592653589793
let closestDoublePiValue: Double = float80pi.floatingPointValue() // 3.141592653589793
let closestFloatPiValue: Float = float80pi.floatingPointValue() // 3.141593
let exactlyCGFloat: CGFloat? = float80pi.floatingPoint() // nil
let exactlyDouble: Double? = float80pi.floatingPoint() // nil
let exactlyFloat: Float? = float80pi.floatingPoint() // nil
来源:https://stackoverflow.com/questions/60773207/swift-casting-a-floatingpoint-conforming-value-to-double