簡體   English   中英

運算符在Swift中使用元組重載

[英]Operator Overloading with Tuples in Swift

運算符重載

Swift 4.1,Xcode 9.3

我試圖在Swift中創建二次方程函數。

在研究這個時,我發現我需要重載一些運算符,以便我可以使用元組和其他數字(在這種情況下為Double ),這是因為我需要使用我的自定義±運算符。 盡管我在二次函數中只使用了Double類型的值,但我決定使用泛型來使我的重載運算符更靈活,以備將來使用。

但是 - 由於某種原因我不明白 - 我收到有關重載/運算符聲明的錯誤。


定制±操作員 - 工作

infix operator ± : AdditionPrecedence

public func ± <T: Numeric>(left: T, right: T) -> (T, T) {
    return (left + right, left - right)
}

二次函數 - 工作

func quadratic(a: Double, b: Double, c: Double) -> (Double, Double) {
    return (-b ± sqrt((b * b) - (4 * a * c))) / (2 * a)
}

超載操作員 - 部分工作¹

//Binary operator '/' cannot be applied to two 'T' operands
func / <T: Numeric>(lhs: (T, T), rhs: T) -> (T, T) { 
    return (lhs.0 / rhs, lhs.1 / rhs)
}
func * <T: Numeric>(lhs: (T, T), rhs: T) -> (T, T) {
    return (lhs.0 * rhs, lhs.1 * rhs)
}
func - <T: Numeric>(lhs: (T, T), rhs: T) -> (T, T) {
    return (lhs.0 - rhs, lhs.1 - rhs)
}
func + <T: Numeric>(lhs: (T, T), rhs: T) -> (T, T) {
    return (lhs.0 + rhs, lhs.1 + rhs)
}

//Binary operator '/' cannot be applied to two 'T' operands
func / <T: Numeric>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs / rhs.0, lhs / rhs.1)
}
func * <T: Numeric>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs * rhs.0, lhs * rhs.1)
}
func - <T: Numeric>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs - rhs.0, lhs - rhs.1)
}
func + <T: Numeric>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs + rhs.0, lhs + rhs.1)
}

1. 我只使用/運算符接收這些錯誤,而不是使用任何其他重載運算符( +-* )。


帶錯誤的重載操作符( / s) - 不工作

//Binary operator '/' cannot be applied to two 'T' operands
func / <T: Numeric>(lhs: (T, T), rhs: T) -> (T, T) { 
    return (lhs.0 / rhs, lhs.1 / rhs)
}

//Binary operator '/' cannot be applied to two 'T' operands
func / <T: Numeric>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs / rhs.0, lhs / rhs.1)
}

假設: 我認為我在重載/運算符本身的聲明中使用運算符/的事實 - 盡管事實上它正在不同的上下文中使用 - 導致錯誤。


最后的問題:

如何在保持重載運算符的靈活性的同時解決錯誤?


獎金問題1:如果我可以(我認為我可能必須返回一個String來完成此操作),我還想制作一個單獨的二次函數,它可以返回一個精確的解決方案?

獎金問題2:如果有人知道如何制作一個可以解決三次方程而不是二次方的單獨函數,那也是值得贊賞的。


Numeric僅聲明+-*運算符。 沒有/Numeric 您需要BinaryIntegerFloatingPoint才能獲得除法。

對於二次方程求解器,我會說FloatingPoint更合適:

func / <T: FloatingPoint>(lhs: T, rhs: (T, T)) -> (T, T) {
    return (lhs / rhs.0, lhs / rhs.1)
}

func / <T: FloatingPoint>(lhs: (T, T), rhs: T) -> (T, T) {
    return (lhs.0 / rhs, lhs.1 / rhs)
}

正如亞歷山大所說,如果你創建一個代表解決方案的枚舉會更好:

enum QuadraticSolution {
    case none
    case one(value: Double)
    case two(value1: Double, value2: Double)
}

func quadratic(a: Double, b: Double, c: Double) -> QuadraticSolution {
    let discriminant = (b * b) - (4 * a * c)
    switch discriminant {
    case 0:
        return .one(value: -b / (2 * a))
    case let x where x < 0:
        return .none
    default:
        let twoSolutions = (-b ± sqrt(discriminant)) / (2 * a)
        return .two(value1: twoSolutions.0, value2: twoSolutions.1)
    }
}

關鍵是定義/何時TFloatingPointBinaryInteger ,而不僅僅是任何Numeric 此外,我建議您使用枚舉,以正確建模二次函數的三種可能結果:

import Foundation

infix operator ± : AdditionPrecedence

public enum QuadraticRoots<T> {
    case two(T, T)
    case one(T)
    case none

    func applyWithSelfOnLeft(_ fn: (T, T) -> T, withOperand value: T) -> QuadraticRoots {
        switch self {
            case let .two(a, b): return .two(fn(a, value), fn(b, value))
            case let .one(a): return .one(fn(a, value))
            case .none: return .none
        }
    }

    func applyWithSelfOnRight(withOperand value: T, _ fn: (T, T) -> T) -> QuadraticRoots {
        switch self {
            case let .two(a, b): return .two(fn(value, a), fn(value, b))
            case let .one(a): return .one(fn(value, a))
            case .none: return .none
        }
    }
}

public func ± <T: Numeric>(left: T, right: T) -> QuadraticRoots<T> {
    return QuadraticRoots.two(left + right, left - right)
}

extension QuadraticRoots where T: Numeric {

    static func + (quadRoots: QuadraticRoots, rhs: T) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnLeft((+), withOperand: rhs)
    }
    static func - (quadRoots: QuadraticRoots, rhs: T) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnLeft((-), withOperand: rhs)
    }
    static func * (quadRoots: QuadraticRoots, rhs: T) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnLeft((*), withOperand: rhs)
    }


    static func + (lhs: T, quadRoots: QuadraticRoots) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnRight(withOperand: lhs, (+))
    }
    static func - (lhs: T, quadRoots: QuadraticRoots) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnRight(withOperand: lhs, (-))
    }
    static func * (lhs: T, quadRoots: QuadraticRoots) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnRight(withOperand: lhs, (*))
    }

    static func discriminantOf(xSquared a: T, x b: T, c: T) -> T { return b*b - 4*a*c }
}

extension QuadraticRoots where T: FloatingPoint {
    static func / (quadRoots: QuadraticRoots, rhs: T) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnLeft((/), withOperand: rhs)
    }

    static func / (lhs: T, quadRoots: QuadraticRoots) -> QuadraticRoots {
        return quadRoots.applyWithSelfOnRight(withOperand: lhs, (/))
    }

    static func solveFrom(xSquared a: T, x b: T, c: T) -> QuadraticRoots {
        let discriminant = self.discriminantOf(xSquared: a, x: b, c: c)
        return (-b ± sqrt(discriminant)) / (2 * a)
    }
}

let a = 5 ± 10
print(a)
print(a + 2)
print(a - 2)
print(a * 2)

print(2 + a)
print(2 - a)
print(2 * a)

//print(a / 2)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM