import Foundation
let operatorPrecedence: [Character: Int] = ["+": 1, "-": 1, "*": 2, "/": 2, "^": 3, "v": 3]
class Calculator {
func run() {
print("请输入数学表达式:")
if let input = readLine() {
do {
let result = try calculate(input)
print("计算结果: \(result)")
} catch {
print("错误: \(error)")
}
} else {
print("输入无效。")
}
}
func calculate(_ expression: String) throws -> Double {
let tokens = try tokenize(expression)
let postfixTokens = infixToPostfix(tokens)
let result = try evaluatePostfix(postfixTokens)
return result
}
private func tokenize(_ expression: String) throws -> [String] {
var tokens: [String] = []
var currentToken = ""
for char in expression {
if char.isNumber || char == "." {
currentToken.append(char)
} else {
if !currentToken.isEmpty {
tokens.append(currentToken)
currentToken = ""
}
if char != " " {
tokens.append(String(char))
}
}
}
if !currentToken.isEmpty {
tokens.append(currentToken)
}
return tokens
}
private func infixToPostfix(_ infixTokens: [String]) -> [String]
{
var output: [String] = []
var stack: [String] = []
for token in infixTokens {
if let number = Double(token) {
output.append(String(number))
} else if token == "(" {
stack.append(token)
} else if token == ")" {
while let top = stack.last, top != "(" {
output.append(stack.removeLast())
}
stack.removeLast()
} else {
while let top = stack.last,
let precedence1 = operatorPrecedence[token.first!],
let precedence2 = operatorPrecedence[top.first!],
precedence1 <= precedence2 {
output.append(stack.removeLast())
}
stack.append(token)
}
}
while !stack.isEmpty {
output.append(stack.removeLast())
}
return output
}
private func evaluatePostfix(_ postfixTokens: [String]) throws -> Double {
var stack: [Double] = []
for token in postfixTokens {
if let number = Double(token) {
stack.append(number)
} else {
let operand2 = stack.removeLast()
let operand1 = stack.removeLast()
switch token {
case "+": stack.append(operand1 + operand2)
case "-": stack.append(operand1 - operand2)
case "*": stack.append(operand1 * operand2)
case "/":
guard operand2 != 0 else {
throw CalculatorError.divisionByZero
}
stack.append(operand1 / operand2)
case "^": stack.append(pow(operand1, operand2))
case "v": stack.append(pow(operand1, 1/operand2))
default:
throw CalculatorError.invalidOperator
}
}
}
return stack.first ?? 0.0
}
}
enum CalculatorError: Error {
case invalidOperator
case divisionByZero
}
let calculator = Calculator()
calculator.run()