/* calculator.go - 计算器核心逻辑 实现了基本的四则运算和括号运算功能 */ package calculator import ( "fmt" "strconv" "strings" ) // Calculator 接口定义了计算器的基本功能 type Calculator interface { Calculate(expression string) (float64, error) GetHistory() []HistoryRecord ClearHistory() } // BasicCalculator 基本计算器实现 type BasicCalculator struct { history []HistoryRecord } // NewCalculator 创建新的计算器实例 func NewCalculator() Calculator { return &BasicCalculator{ history: make([]HistoryRecord, 0), } } // Calculate 计算数学表达式 func (c *BasicCalculator) Calculate(expression string) (float64, error) { // 清理输入 expr := strings.ReplaceAll(expression, " ", "") if expr == "" { return 0, fmt.Errorf("表达式不能为空") } // 验证表达式 if err := c.validateExpression(expr); err != nil { return 0, err } // 解析和计算 result, err := c.evaluateExpression(expr) if err != nil { return 0, err } // 添加到历史记录 c.addToHistory(expression, result) return result, nil } // GetHistory 获取计算历史 func (c *BasicCalculator) GetHistory() []HistoryRecord { // 返回历史记录的副本 history := make([]HistoryRecord, len(c.history)) copy(history, c.history) return history } // ClearHistory 清空历史记录 func (c *BasicCalculator) ClearHistory() { c.history = make([]HistoryRecord, 0) } // validateExpression 验证表达式的有效性 func (c *BasicCalculator) validateExpression(expr string) error { if len(expr) == 0 { return fmt.Errorf("表达式不能为空") } // 检查括号匹配 parentheses := 0 for _, char := range expr { switch char { case '(': parentheses++ case ')': parentheses-- if parentheses < 0 { return fmt.Errorf("括号不匹配") } } } if parentheses != 0 { return fmt.Errorf("括号不匹配") } // 检查有效字符 validChars := "0123456789+-*/.() " for _, char := range expr { if !strings.ContainsRune(validChars, char) { return fmt.Errorf("包含无效字符: %c", char) } } // 检查连续运算符 operators := "+-*/" for i := 0; i < len(expr)-1; i++ { if strings.ContainsRune(operators, rune(expr[i])) && strings.ContainsRune(operators, rune(expr[i+1])) { return fmt.Errorf("连续的运算符") } } return nil } // evaluateExpression 计算表达式的值 func (c *BasicCalculator) evaluateExpression(expr string) (float64, error) { // 处理括号 for strings.Contains(expr, "(") { // 找到最内层的括号 start := -1 for i, char := range expr { if char == '(' { start = i } else if char == ')' { if start == -1 { return 0, fmt.Errorf("括号不匹配") } // 计算括号内的表达式 subExpr := expr[start+1 : i] subResult, err := c.evaluateSimpleExpression(subExpr) if err != nil { return 0, err } // 替换括号表达式为结果 expr = expr[:start] + fmt.Sprintf("%g", subResult) + expr[i+1:] break } } } // 计算简单表达式(无括号) return c.evaluateSimpleExpression(expr) } // evaluateSimpleExpression 计算简单表达式(无括号) func (c *BasicCalculator) evaluateSimpleExpression(expr string) (float64, error) { if expr == "" { return 0, fmt.Errorf("空表达式") } // 解析表达式为标记 tokens, err := c.tokenize(expr) if err != nil { return 0, err } if len(tokens) == 0 { return 0, fmt.Errorf("空表达式") } // 如果只有一个标记,直接返回数值 if len(tokens) == 1 { return strconv.ParseFloat(tokens[0], 64) } // 先处理乘法和除法 for i := 1; i < len(tokens); i += 2 { if i >= len(tokens) { break } operator := tokens[i] if operator == "*" || operator == "/" { left, err := strconv.ParseFloat(tokens[i-1], 64) if err != nil { return 0, fmt.Errorf("无效的数字: %s", tokens[i-1]) } right, err := strconv.ParseFloat(tokens[i+1], 64) if err != nil { return 0, fmt.Errorf("无效的数字: %s", tokens[i+1]) } var result float64 if operator == "*" { result = left * right } else { if right == 0 { return 0, fmt.Errorf("除零错误") } result = left / right } // 替换三个标记为结果 newTokens := make([]string, 0, len(tokens)-2) newTokens = append(newTokens, tokens[:i-1]...) newTokens = append(newTokens, fmt.Sprintf("%g", result)) newTokens = append(newTokens, tokens[i+2:]...) tokens = newTokens i -= 2 // 调整索引 } } // 再处理加法和减法 result, err := strconv.ParseFloat(tokens[0], 64) if err != nil { return 0, fmt.Errorf("无效的数字: %s", tokens[0]) } for i := 1; i < len(tokens); i += 2 { if i+1 >= len(tokens) { break } operator := tokens[i] operand, err := strconv.ParseFloat(tokens[i+1], 64) if err != nil { return 0, fmt.Errorf("无效的数字: %s", tokens[i+1]) } switch operator { case "+": result += operand case "-": result -= operand default: return 0, fmt.Errorf("未知的运算符: %s", operator) } } return result, nil } // tokenize 将表达式分解为标记 func (c *BasicCalculator) tokenize(expr string) ([]string, error) { var tokens []string var current strings.Builder for i, char := range expr { switch char { case '+', '-', '*', '/': // 处理负号 if char == '-' && (i == 0 || expr[i-1] == '(' || strings.ContainsRune("+-*/", rune(expr[i-1]))) { current.WriteRune(char) continue } // 保存当前数字 if current.Len() > 0 { tokens = append(tokens, current.String()) current.Reset() } // 保存运算符 tokens = append(tokens, string(char)) case ' ': // 忽略空格 continue default: // 数字或小数点 current.WriteRune(char) } } // 保存最后的数字 if current.Len() > 0 { tokens = append(tokens, current.String()) } return tokens, nil } // addToHistory 添加计算记录到历史 func (c *BasicCalculator) addToHistory(expression string, result float64) { record := HistoryRecord{ Expression: expression, Result: result, } c.history = append(c.history, record) // 限制历史记录数量 const maxHistory = 100 if len(c.history) > maxHistory { c.history = c.history[len(c.history)-maxHistory:] } }