Create an RPN Calculator in Swift

Asked 2 years ago, Updated 2 years ago, 81 views

I am currently studying Swift.
Now that I understand the basic syntax, I want to make a calculator that can calculate correctly.

I understand that the RPN calculator is a useful introduction to programming correct formulas.

I could write a program that can calculate RPN-like from a string, but I don't really understand how to make the formula RPN-oriented.

Example) For 1+3+4×2, if you calculate from the beginning, it will be 16
  The string "1 3 4 2 × + +" is calculated by RPN to 12

Reference
http://www.rpn.jp/lecture/rpn/rpn100/rpn101.html
https://knowledge.sakura.ad.jp/220/

I'd like to program the RPN string, what should I do?
You can use various buttons to enter.

*Swift doesn't know how to write stack, so it's quite a forced source.

funcalcString(_str:String){

    letarr: [String] = str.components(separatedBy:"")
    var stack : String = [ ]

    // split
    for dat in ar {
        // print(dat)
        if isOnlyNumber(dat){
            // Numeric only
            stack.append(dat)
        } else{
            // not just numbers
            if(isOnlyArthmatic(dat)){

                // More than one stack?
                if(stack.count>=2){
                    Let num1: Double=Double(stack[stack.count-1])!
                    Let num2: Double=Double(stack[stack.count-2])!
                    varres —Double = 0

                    // Delete two elements
                    stack.removeLast()
                    stack.removeLast()

                    // calculation
                    switch dat {
                    case"+":
                        res=num1+num2
                    case"-":
                        res=num1-num2
                    case "x":
                        res=num1*num2
                    case " "":
                        res=num1/num2
                    default:
                        break
                    }

                    stack.append(String(res))

                } else {
                    print("error stack.count=>"+String(stack.count))
                }

            } else {
                print("error dat=>"+dat)
            }

        }
    }

    print(stack.count)
    print(stack[stack.count-1])


}

// Check if it is only.
funcisOnlyNumber(_str:String) - >Bool{
    let predict=NSPredicate(format: "SELF MATCHES'\\\d+'")
    return predictor.evaluate (with:str)
}

// check for signs only
funcisOnlyArthmatic(_str:String) - >Bool{
    if(str=="+"||str=="-"|str=="×"||str==" ""){
        return true
    }
    return false
}

swift xcode swift4

2022-09-30 16:27

1 Answers

Nice to meet you. "As for the question, ""I can handle the RPN expression expressed in a string, but how should I express the stack?"""

You can use various buttons to enter.

Therefore, if the button is pressed on the connection between the IBAction, I will reply as if I have reached the level where I can write a program to run this function.

First of all, I think you can write the stack like this on Swift.There may be a better way to write just one example, but I think it's enough for practical use.

structure Stack <Float > {
    var stack —Array<Float>=Array<Float>()

    mutating func push(_item:Float)->Void{
        stack.append(item)
    }// end push

    mutating func pop()->Float{
        return stack.removeLast()
    }// end pop
}// end structure Stack

(Because we use structure instead of class, we declare muting before func)

In order to display the calculation results, I think it would be good to update the label with the calculation results.

By the way, regarding the source of the question, it works as it is, but

let num1: Double=Double (stack[stack.count-1])!
Let num2: Double=Double(stack[stack.count-2])!
varres —Double = 0

    // Delete two elements
stack.removeLast()
stack.removeLast()

Yes, but

let num1: Double=Double(stack.removeLast())!
Let num2: Double=Double(stack.removeLast())!
varres —Double = 0

I think it would be better to stack up.

Instead, if you want an app that has a display part and a button part, and you press the button to display the values and calculation results in the order of RPN input, you can see the appearance of an ordinary calculator.

In addition, I think that the screen will require numeric buttons (0-9 and decimal buttons), operator buttons (+, -, x, ,, other functions, etc.) and enter buttons.
Once these buttons have been placed, create three actions to connect.

First of all, I think that each of the 0-9 and the +/- and . buttons are pressed to create a number according to the button you press.
That's why I created this class.

class DecimalNumber {
    private var number —Float
    private var friction —Float

    init(){
        number = 0
        friction = 0
    }// end init

    public funcaddDigit(_digit:Int){
        if reaction == 0 {
            number* = 10
            number + = digit
        } else{
            number + = digit*fraction
            friction* = 0.1
        }// end if digit is integer part or fractional part
    }// end addDigit

    public func changeSign(){
        number* = -1
    }// endchangeSign

    public func switchToFract(){
        ifaction!=0 {return}
        friction = 0.1
    }// end switchToFract

    public func getNumber()->Float{
        let currentNumber —Float=number
        number = 0
        return currentNumber
    }// end getNumber
}// end class Digits

By creating a class like this (for example, decimal),

  • 0 -9 button, then decimal.addDigit
  • +/- button, decimal.changeSign()
  • When the
  • . button is pressed, decimal.switchToFract()

While running , IBAction corresponding to each button is used to += the characters of the button pressed in the numeric display field of the calculator.

Then, when the Enter button or the Function button is pressed, push the number from the decimal to the stack.In this case, the instance of Stack is named stack and

  • When the Enter button is pressed, take the number from decimal and just stack.push(decimal.getNumber()) to return to the next input queue

  • When the non-enter operator button is pressed,
    1stack.push(decimal.getNumber()) just like Enter.
    2 Take as many values from the stack as the operator of the pressed button (numN=stack.pop()) and calculate with the operator
    3 Rewrite the results of the calculation to the end of the stack in stack.push() 4 Display the last digit of the stack in the results section

When the Enter button is pressed, take the number from decimal and just stack.push(decimal.getNumber()) to return to the next input queue

If the non-enter operator button is pressed,
1stack.push(decimal.getNumber()) just like Enter.
2 Take as many values from the stack as the operator of the pressed button (numN=stack.pop()) and calculate with the operator
3 Rewrite the results of the calculation to the end of the stack in stack.push() 4 Display the last digit of the stack in the results section

"By doing so, I think we can create a minimum ""calculator application that inputs numbers and calculates by pressing the button."""


2022-09-30 16:27

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.