import Foundation
func evaluate(_ expression: String) throws -> Double {
enum EvaluationError: Error {
case unbalancedParentheses
case invalidToken(String)
case divisionByZero
}
let separator = CharacterSet.whitespaces.union(.newlines)
let tokens = expression.components(separatedBy: separator).filter { !$0.isEmpty }
var values = [Double]()
var ops = [Character]()
let precedence: [Character: Int] = ["+": 1, "-": 1, "*": 2, "/": 2 , "^": 3]
func applyOp(_ op: Character, rhs: Double, lhs: Double) throws -> Double {
switch op {
case "+": return lhs + rhs
case "-": return lhs - rhs
case "*": return lhs * rhs
case "/":
guard rhs != 0 else { throw EvaluationError.divisionByZero }
return lhs / rhs
case "^": return pows(lhs, rhs)
default: fatalError("Unsupported operation")
}
}
func pows(_ base: Double, _ exponent: Double) -> Double {
let intPart = Int(exponent)
var result = 1.0
for _ in 0..<intPart {
result *= base
}
return result
}
func hasPrecedence(op1: Character, over op2: Character) -> Bool {
guard let prec1 = precedence[op1], let prec2 = precedence[op2] else { return false }
return prec1 >= prec2
}
for token in tokens {
if let value = Double(token) {
values.append(value)
} else if token == "(" {
ops.append("(")
} else if token == ")" {
while !ops.isEmpty && ops.last != "(" {
let op = ops.removeLast()
let rhs = values.removeLast()
let lhs = values.removeLast()
do{
values.append(try applyOp(op, rhs: rhs, lhs: lhs))
} catch{
print("error:\(error)")
}
}
if !ops.isEmpty && ops.last == "(" {
ops.removeLast()
} else {
throw EvaluationError.unbalancedParentheses
}
} else if let firstChar = token.first, precedence[firstChar] != nil {
while !ops.isEmpty && ops.last != "(" && hasPrecedence(op1:ops.last!, over: firstChar) {
let op = ops.removeLast()
let rhs = values.removeLast()
let lhs = values.removeLast()
do{
values.append(try applyOp(op, rhs: rhs, lhs: lhs))
} catch{
print("error:\(error)")
}
}
ops.append(firstChar)
} else {
throw EvaluationError.invalidToken(token)
}
}
while !ops.isEmpty {
if ops.last == "(" {
throw EvaluationError.unbalancedParentheses
}
let op = ops.removeLast()
let rhs = values.removeLast()
let lhs = values.removeLast()
do{
values.append(try applyOp(op, rhs: rhs, lhs: lhs))
}catch{
print("error:\(error)")
}
}
guard values.count == 1 else { throw EvaluationError.unbalancedParentheses }
return values.first!
}
func applyOp_Complx(_ op: Character, rhs: Complex, lhs: Complex) -> Complex? {
switch op {
case "+": return lhs + rhs
case "-": return lhs - rhs
case "*": return lhs * rhs
case "/": return lhs / rhs
default: return nil
}
}
func printComplex(_ c: Complex) {
print("复数:\(c.real) + \(c.imaginary)i")
}
func parseComplexFromString(_ input: String) -> Complex? {
let scanner = Scanner(string: input)
var realPart: Double = 0.0
var imaginaryPart: Double = 0.0
var hasPlusSign = false
if scanner.scanDouble(&realPart) && scanner.atEnd {
return Complex(real: realPart, imaginary: 0.0)
}
if scanner.scanString("+", into: nil) {
hasPlusSign = true
} else if scanner.scanString("-", into: nil) {
imaginaryPart = -1.0
}
if !hasPlusSign && !scanner.atEnd {
return nil
}
if scanner.scanDouble(&imaginaryPart) && scanner.scanString("i", into: nil) && scanner.atEnd {
return Complex(real: realPart, imaginary: imaginaryPart)
}
return nil
}
repeat {
print("请选择操作:1 - 计算,2 - 复数, 0 - 退出")
if let operation = readLine(), let op = Int(operation) {
switch op {
case 1:
print("请输入一个数学表达式:")
if let input = readLine()?.trimmingCharacters(in: .whitespacesAndNewlines) {
do {
let result = try evaluate(input)
print("\(input) = \(result)")
} catch {
print("表达式求值错误:\(error)")
}
} else {
print("未输入有效的表达式。")
}
case 2:
print("第一个复数")
let complx1 = parseComplexFromString(readLine())
print("操作")
let op1 = readLine()
print("第二个复数")
let complx2 = parseComplexFromString(readLine())
guard let complxResult = applyOp_Complx(op1, rhs: complx2, lhs: complx1) else {
print("无效的操作。")
continue
}
print("\(printComplex(complx1)) \(op1) \(printComplex(complx2)) = \(printComplex(complxResult))")
case 0:
exit(EXIT_SUCCESS)
default:
print("无效的操作。")
}
} else {
print("未输入有效的操作。")
}
} while true