I'm hoping someone could help me fix a bug in my calculator that I dont know how to get around.
For starters, I'm making a little program that models a calculator using immediate execution. As an overview, I had to dig through the internet to find out how immediate execution works for calculators so here's an explanation.
Traditional scientific calculators that respond immediately to key presses have an X and a Y register. The X register is hidden and the Y register appears on the display. When you enter a value it is shifted into the Y register. If you press a binary operator key like + or * the value in the Y register is copied into the X register, the operation is stored, and the Y register is set to accept a new entry. If you then press another binary operator key then the X and Y registers are combined using the stored pending operator, the result is placed in the X register, the key press is stored as a new pending operator, and the Y register is reset to accept a new entry. There are variations around this for the = key (a no-op), for example. Citation
So far, I have implemented this in Swift using a superclass (AbstractCalculator) and a subclass of it (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 } }
And to test out the calculators' functionality and test I made a small simple subclass of AbstractBinaryCalculator called IntegerCalculator.
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) } }
I then began to test out the code by running tests and all of them passed until I got to "testCalculation9" where I just don't know how to fix it. Can someone help me fix this bug?
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") } }
https://stackoverflow.com/questions/65839427/how-to-write-an-algorithm-that-mimics-a-calculator-using-immediate-execution January 22, 2021 at 12:44PM
没有评论:
发表评论