首页 > 解决方案 > 如何使用立即执行编写模拟计算器的算法

问题描述

我希望有人可以帮助我修复我的计算器中的一个我不知道如何解决的错误。

对于初学者,我正在制作一个使用立即执行来模拟计算器的小程序。作为概述,我不得不在互联网上挖掘,以了解计算器的即时执行是如何工作的,所以这里有一个解释。

立即响应按键的传统科学计算器具有 X 和 Y 寄存器。X 寄存器被隐藏,Y 寄存器出现在显示屏上。当您输入一个值时,它会移入 Y 寄存器。如果您按下 + 或 * 之类的二元运算符键,则 Y 寄存器中的值被复制到 X 寄存器中,操作被存储,并且 Y 寄存器被设置为接受新条目。如果您随后按下另一个二元运算符键,则使用存储的未决运算符组合 X 和 Y 寄存器,结果放在 X 寄存器中,按键存储为新的未决运算符,并且 Y 寄存器重置为接受一个新的条目。例如,= 键(无操作)在这方面有一些变化。引文

到目前为止,我已经在 Swift 中使用超类 (AbstractCalculator) 和它的子类 (AbstractBinaryCalculator) 实现了这一点

open class AbstractCalculator {

    public var _currentOperator : String = ""
    public var _currentNumberEnteredIn : String = ""

    public init() {}

    /**
     Inputs a single digit into the current number being entered
     - Parameter digit: A single digit
     */
    open func inputDigit(_ digit : Character) {
        self._currentNumberEnteredIn += String(digit)
    }
    
    open func inputEqualsSign() {
        fatalError("Need to override in subclasses")
    }
            
    open func inputOperator(_ calculatorOperator : String) {
        fatalError("Need to override in subclasses")
    }


}



open class AbstractBinaryCalculator : AbstractCalculator {

    public var _operatorDictionary = [String : ((String, String) -> String)]()

    public var _accumulatedResult : String = ""
    
    open override func inputDigit(_ digit: Character) {
        self._currentNumberEnteredIn += String(digit)
    }

    open func _saveCurrentNumberToAccumulatedResultIfNeeded() {
        if self._accumulatedResult.isEmpty {
            self._accumulatedResult = self._currentNumberEnteredIn
        }
    }

    open override func inputOperator(_ calculatorOperator: String) {
        if canPerformCalculation() {
            self._performCalculationAndSetAccumulatedResult()
        }
        self._currentOperator = calculatorOperator
        self._saveCurrentNumberToAccumulatedResultIfNeeded()
        self._currentNumberEnteredIn = ""
    }

    open override func inputEqualsSign() {
        if canPerformCalculation() {
            self._performCalculationAndSetAccumulatedResult()
        }
    }

    public func canPerformCalculation() -> Bool {
        let hasAccumulatedResult = !self._accumulatedResult.isEmpty
        let hasCurrentOperator = !self._currentOperator.isEmpty
        let isCurrentNumberEntered = !self._currentNumberEnteredIn.isEmpty
        return (hasAccumulatedResult && hasCurrentOperator && isCurrentNumberEntered)
    }

    open func _performCalculationAndSetAccumulatedResult() {
        let result = getResultUsingCurrentFunctionOnAccumulatedResultAndCurrentNumber()
        self._accumulatedResult = result
    }

    public func getResultUsingCurrentFunctionOnAccumulatedResultAndCurrentNumber() -> String {
        let function = getMathOperatorFunction()
        let currentNumberEnteredIn = self._currentNumberEnteredIn
        let accumulatedResult = self._accumulatedResult
        let result = function(accumulatedResult, currentNumberEnteredIn)
        return result
    }

    public func getMathOperatorFunction() -> (String, String) -> String {
        let mathOperator = self._currentOperator
        let function = self._operatorDictionary[mathOperator]!
        return function
    }

    /**
     Adds a new function to the calculator.
     - Parameter operatorFunction: An AbstractCalculatorOperator object
     */
    public func addOperatorFunction(_ operatorFunction : AbstractBinaryCalculatorOperator) {
        let mathOperator = operatorFunction.getOperatorSymbol()
        let function = operatorFunction.getFunction()
        self.addOperatorFunction(mathOperator, function: function)
    }

    /**
     Adds a new function to the calculator.
     - Parameter operatorSymbol: The symbol for the operator (+,-,% etc)
     - Parameter function: The function that will perform logic.
     */
    public func addOperatorFunction(_ operatorSymbol : String, function : @escaping (String, 
String) -> String) {
        self._listOfMathOperators.append(operatorSymbol)
        self._operatorDictionary[operatorSymbol] = function
    }


}

为了测试计算器的功能并进行测试,我创建了一个名为 IntegerCalculator 的 AbstractBinaryCalculator 的简单子类。

public class IntegerCalculator : AbstractBinaryCalculator {

    public override init() {
        super.init()
        self.addOperatorFunction("+", function: self.add(number1:number2:))
        self.addOperatorFunction("-", function: self.subtract(number1:number2:))
        self.addOperatorFunction("*", function: self.multiply(number1:number2:))
    }
    
    private func add(number1 : String, number2 : String) -> String {
        let result = Int(number1)! + Int(number2)!
        return String(result)
    }

    private func subtract(number1 : String, number2 : String) -> String {
        let result = Int(number1)! - Int(number2)!
        return String(result)
    }

    private func multiply(number1 : String, number2 : String) -> String {
        let result = Int(number1)! * Int(number2)!
        return String(result)
    }

}

然后我开始通过运行测试来测试代码,所有这些都通过了,直到我到达“testCalculation9”,我只是不知道如何修复它。有人可以帮我修复这个错误吗?

import XCTest
@testable import AbstractCalculator

final class AbstractCalculatorTests: XCTestCase {


func testCalculation1() throws {
    
    let intCalculator = IntegerCalculator()
    
    XCTAssertEqual(intCalculator._currentNumberEnteredIn, "", "Incorrect")
    
    
}

func testCalculation2() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "2", "Incorrect")

    integerCalculator.inputOperator("+")

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "2", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")
}

func testCalculation3() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "5", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "2", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")
    XCTAssertTrue(integerCalculator.canPerformCalculation())
}

func testCalculation4() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "5", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "7", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")
}

func testCalculation5() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")
    integerCalculator.inputEqualsSign()
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "5", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "12", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")
}

func testCalculation6() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("*")
    integerCalculator.inputDigit("2")
    integerCalculator.inputEqualsSign()
    integerCalculator.inputEqualsSign()
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "2", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "16", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "*", "Incorrect")
}

func testCalculation7() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("7")
    integerCalculator.inputOperator("*")
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "5", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "23", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")

    //Need setting for pemdas complient and non pemdas compliment.

}

func testCalculation8() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("7")
    integerCalculator.inputOperator("*")
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")
    integerCalculator.inputEqualsSign()
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "5", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "28", "Incorrect")
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")

    //Need setting for pemdas complient and non pemdas compliment.

}

func testCalculation9() throws {
    let integerCalculator = IntegerCalculator()
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("7")
    integerCalculator.inputOperator("*")
    integerCalculator.inputDigit("2")
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("5")
    integerCalculator.inputEqualsSign()
    integerCalculator.inputOperator("+")
    integerCalculator.inputDigit("9")
    integerCalculator.inputEqualsSign()

    XCTAssertEqual(integerCalculator._currentNumberEnteredIn, "9", "Incorrect")
    XCTAssertEqual(integerCalculator._accumulatedResult, "32", "Incorrect") //XCTAssertEqual failed: ("37") is not equal to ("32") 
    XCTAssertEqual(integerCalculator._currentOperator, "+", "Incorrect")

    

}


}

标签: swiftalgorithm

解决方案


推荐阅读