Converting Infix Expressions to Postfix and Evaluating Them in Swift
This article explains how to transform a typical infix arithmetic expression such as "8 - (6 + 4 / 2 - 1) * 2" into a postfix (Reverse Polish) form using Swift, then evaluates the postfix expression step by step with custom Swift functions and also shows a shortcut using NSExpression.
Background : While developing a "24‑point challenge" app the author needed to compute the result of arbitrary arithmetic strings like 8 - (6 + 4 / 2 - 1) * 2 and show the whole calculation process.
Infix vs. Postfix : An infix expression places operators between operands, which is natural for humans but difficult for computers. Converting it to postfix (Reverse Polish) puts the operator after its operands, making evaluation straightforward.
Conversion algorithm : The algorithm uses two arrays to simulate a stack (one for numbers, one for operators). It scans the expression from left to right, handling parentheses, operator precedence, and finally outputs the postfix array.
Swift implementation – conversion : func converExpressionToSuffixExpression(_ expressionStr: String) -> [String] { var suffixExpressionList: [String] = [] var operatorExpressionList: [String] = [] for item in expressionStr { let itemStr = String(item) if itemStr == " " { continue } if item.isNumber { suffixExpressionList.append(itemStr) } else { if operatorExpressionList.isEmpty { operatorExpressionList.append(itemStr) } else { if itemStr == ")" { let temp = handleAppendExpressionList(operatorExpressionList, suffixList: suffixExpressionList, isRightBracket: true) operatorExpressionList = temp.l1 suffixExpressionList = temp.l2 } else { let lastStr = operatorExpressionList.last! let isItemPriorityHigh = isFirstOperatorPriorityHigh(first: itemStr, second: lastStr) if isItemPriorityHigh || itemStr == "(" || lastStr == "(" { operatorExpressionList.append(itemStr) } else { let temp = handleAppendExpressionList(operatorExpressionList, suffixList: suffixExpressionList, isRightBracket: false) operatorExpressionList = temp.l1 suffixExpressionList = temp.l2 operatorExpressionList.append(itemStr) } } } } } while !operatorExpressionList.isEmpty { if let last = operatorExpressionList.popLast() { suffixExpressionList.append(last) } } return suffixExpressionList } func handleAppendExpressionList(_ operatorList: [String], suffixList: [String], isRightBracket: Bool) -> ([String], [String]) { var operatorExpressionList = operatorList var suffixExpressionList = suffixList var lastStr = operatorExpressionList.last repeat { guard let tempLastStr = operatorExpressionList.popLast() else { break } lastStr = tempLastStr if tempLastStr != "(" { suffixExpressionList.append(tempLastStr) } else if isRightBracket { operatorExpressionList.append("(") } } while lastStr != "(" && lastStr != "" return (operatorExpressionList, suffixExpressionList) } func isFirstOperatorPriorityHigh(first: String, second: String) -> Bool { let isFirst = isMultiplyOrDivideOperator(itemStr: first) let isSecond = isMultiplyOrDivideOperator(itemStr: second) return isFirst && !isSecond } func isMultiplyOrDivideOperator(itemStr: String) -> Bool { return ["*", "x", "×", "X", "/", "÷"].contains(itemStr) }
Postfix evaluation principle : Scan the postfix array from left to right; when an operator is encountered, take the two preceding numbers, compute a op b , replace the three elements with the result, and continue until a single element remains.
Swift implementation – evaluation : func calculatorExpressionList(_ expressionList: [String]) -> Double { if expressionList.count == 1 { return (expressionList.first as NSString?)?.doubleValue ?? 0.0 } var targetList = expressionList for (index, item) in expressionList.enumerated() { if isOperator(item) { let a = expressionList[index - 2] let b = expressionList[index - 1] let r = calculator(a, item, b) targetList[index - 2] = r targetList.removeSubrange(Range(NSRange(location: index - 1, length: 2))!) break } } return calculatorExpressionList(targetList) } func calculator(_ a: String, _ op: String, _ b: String) -> String { let aValue = (a as NSString).doubleValue let bValue = (b as NSString).doubleValue var result: Double = 0.0 switch op { case "+": result = aValue + bValue case "-": result = aValue - bValue case "*", "×", "x", "X": result = aValue * bValue case "/", "÷": if bValue != 0 { result = aValue / bValue } default: break } return String(format: "%f", result) } func isOperator(_ str: String) -> Bool { if isMultiplyOrDivideOperator(itemStr: str) { return true } return str == "+" || str == "-" }
Shortcut with NSExpression : For simple calculations the built‑in NSExpression class can evaluate a formatted string directly. let expressionStr = "2 + 3 * (5 - 1)" let formatted = expressionStr.replacingOccurrences(of: " ", with: "") let expression = NSExpression(format: formatted) if let result = expression.expressionValue(with: nil, context: nil) as? NSNumber { print(result) }
Summary : The article provides a complete Swift solution for converting infix arithmetic strings to postfix notation, evaluating the postfix expression, and an alternative using NSExpression . The full source code is available at GitHub .
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.