func calculate(numStack *[]float64, opStack *[]rune) { b := (*numStack)[len(*numStack)-1] a := (*numStack)[len(*numStack)-2] op := (*opStack)[len(*opStack)-1]
result := applyOperator(a, b, op) *numStack = append(*numStack, result) }
func applyOperator(a, b float64, op rune) float64 { switch op { case '+': return a + b case '-': return a - b case '*': return a * b case '/': if b == 0 { panic("деление на ноль") } return a / b default: return 0 } }
package main
import (
"errors"
"fmt"
"strconv"
"strings"
"unicode"
)
func Calc(expression string) (float64, error) {
priority := map[rune]int{
'+': 1,
'-': 1,
'*': 2,
'/': 2,
}
var numStack []float64
var opStack []rune
hasNumber := false
expression = strings.ReplaceAll(expression, " ", "")
if len(expression) == 0 {
return 0, errors.New ("пустое выражение")
}
for i := 0; i < len(expression); i++ {
ch := rune(expression[i])
switch {
case unicode.IsDigit(ch):
start := i
for i < len(expression) && unicode.IsDigit(rune(expression[i])) {
i++
}
num, _ := strconv.ParseFloat(expression[start:i], 64)
numStack = append(numStack, num)
hasNumber = true
i--
case ch == '+' || ch == '-':
if i == 0 || expression[i-1] == '(' || len(opStack) > 0 && opStack[len(opStack)-1] == '(' {
numStack = append(numStack, 0)
}
for len(opStack) > 0 && priority[opStack[len(opStack)-1]] >= priority[ch] {
calculate(&numStack, &opStack)
}
opStack = append(opStack, ch)
case ch == '*' || ch == '/':
for len(opStack) > 0 && priority[opStack[len(opStack)-1]] >= priority[ch] {
calculate(&numStack, &opStack)
}
opStack = append(opStack, ch)
case ch == '(':
opStack = append(opStack, ch)
case ch == ')':
for len(opStack) > 0 && opStack[len(opStack)-1] != '(' {
calculate(&numStack, &opStack)
}
if len(opStack) == 0 {
return 0, errors.New ("несоответствие скобок")
}
opStack = opStack[:len(opStack)-1]
default:
return 0, fmt.Errorf("неверный символ '%c'", ch)
}
}
if !hasNumber {
return 0, errors.New ("нет чисел в выражении")
}
for len(opStack) > 0 {
calculate(&numStack, &opStack)
}
if len(numStack) == 1 {
return numStack[0], nil
}
return 0, errors.New ("некорректное выражение")
}
func calculate(numStack *[]float64, opStack *[]rune) {
b := (*numStack)[len(*numStack)-1]
a := (*numStack)[len(*numStack)-2]
op := (*opStack)[len(*opStack)-1]
*numStack = (*numStack)[:len(*numStack)-2]
*opStack = (*opStack)[:len(*opStack)-1]
result := applyOperator(a, b, op)
*numStack = append(*numStack, result)
}
func applyOperator(a, b float64, op rune) float64 {
switch op {
case '+':
return a + b
case '-':
return a - b
case '*':
return a * b
case '/':
if b == 0 {
panic("деление на ноль")
}
return a / b
default:
return 0
}
}