代码之家  ›  专栏  ›  技术社区  ›  Noah Wilder

Swift中元组的操作符重载

  •  3
  • Noah Wilder  · 技术社区  · 7 年前

    运算符重载

    Swift 4.1,Xcode 9.3

    我想用Swift做一个二次方程函数。

    在处理这个问题时,我发现我需要重载一些操作符,这样我就可以处理元组和其他数字( 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)
    }
    

    假设: 我认为我使用运算符 / 在重载的声明内 / 运算符本身(尽管它正在不同的上下文中使用)会导致错误。


    最后一个问题:

    如何在保持重载运算符灵活性的同时解决错误?


    如果可以(我想我可能必须返回 String 为了实现这一点),我还想制作一个单独的二次函数,它可以返回 准确的 解决方案

    奖金问题2: 还有,如果有人知道如何制作一个单独的函数来解决 立方体的


    2 回复  |  直到 5 年前
        1
  •  3
  •   Sweeper    7 年前

    Numeric 仅声明 + ,则, - * 操作员。没有 / 在里面 数字 .你需要 BinaryInteger 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)
    }
    

    正如Alexander所说,如果您创建一个表示解决方案的枚举会更好:

    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)
        }
    }
    
        2
  •  2
  •   Alexander    7 年前

    关键是定义 / 什么时候 T FloatingPoint BinaryInteger ,而不仅仅是任何 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)