Swift: приведение значения, соответствующего FloatingPoint, к Double - PullRequest
1 голос
/ 20 марта 2020

Я пишу расширение для протокола FloatingPoint. Я хочу привести его к удвоению любым возможным способом.

extension FloatingPoint {
    var toDouble: Double {
        return Double(exactly: self) ?? 0 //compile error
    }
}

Я бы предпочел не говорить о том, чего я пытаюсь достичь, чтобы мы могли сосредоточиться только на вышеуказанной проблеме. Я предпочел бы услышать, что это невозможно сделать таким образом, вместо того, чтобы получить действительный обходной путь для более крупной проблемы, которую я пытаюсь решить.

Я пытался использовать разные конструкторы Double, но, возможно, я не пытался достаточно сложно.

1 Ответ

1 голос
/ 20 марта 2020

Проблема в том, что вам нужно расширить BinaryFloatingPoint вместо FloatingPoint протокола:

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) }
}

Тестирование игровой площадки

let cgFloat: CGFloat = .pi                    // 3.141592653589793

let exactlyDouble = cgFloat.double            // 3.141592653589793
let closestDoubleValue = cgFloat.doubleValue  // 3.141592653589793

Вы также можете создать обобщенные c методы для возврата любого типа с плавающей запятой, который соответствует протоколу BinaryFloatingPoint:

extension BinaryFloatingPoint {
    func floatingPoint<F: BinaryFloatingPoint>() -> F? { F(exactly: self) }
    func floatingPointValue<F: BinaryFloatingPoint>() -> F { .init(self) }
}

Тестирование игровой площадки

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
...