Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Module Module1
- ''' <summary>
- ''' Вычисляет арифметическое выражение с помощью алгоритма Бауэра и Замельзона.
- ''' </summary>
- Public Function CalculateString(expression As String) As Double
- Dim normalizedExpression As String = PreprocessString(expression)
- translatorStack = New CustomStack(Of String)()
- interpreterStack = New CustomStack(Of Double)()
- translatorStack.Push(EmptyOperation)
- For Each s As String In (normalizedExpression & Space(1) & EmptyOperation).Split(" "c)
- Dim value As Double
- If Double.TryParse(s, value) Then
- interpreterStack.Push(value)
- Else
- Dim lastOperationInStack As String = translatorStack.Peek()
- transitionTable(VerticalIndexesMap(lastOperationInStack), HorizontalIndexesMap(s))(s)
- End If
- Next
- Return interpreterStack.Peek()
- End Function
- Private Const EmptyOperation As String = "$"
- Private Const OpeningBracket As String = "("
- Private Const Plus As String = "+"
- Private Const Minus As String = "-"
- Private Const Multiplication As String = "*"
- Private Const Division As String = "/"
- Private Const ClosingBracket As String = ")"
- 'Словарь, связывающий строковое обозначение арифметических операций и функции, их вычисляющие.
- Private arithmeticalFunctions As Dictionary(Of String, Func(Of Double, Double, Double)) = New Dictionary(Of String, Func(Of Double, Double, Double))() From {
- {Plus, Function(a, b) a + b},
- {Minus, Function(a, b) a - b},
- {Multiplication, Function(a, b) a * b},
- {Division, Function(a, b) a / b}
- }
- Private translatorStack As CustomStack(Of String)
- Private interpreterStack As CustomStack(Of Double)
- Private f1 As Action(Of String) = Sub(inputOperation As String)
- translatorStack.Push(inputOperation)
- End Sub
- Private f2 As Action(Of String) = Sub(inputOperation As String)
- Dim lastOperationInStack As String = translatorStack.Pop()
- Dim operand2 As Double = interpreterStack.Pop()
- Dim operand1 As Double = interpreterStack.Pop()
- Dim result As Double = arithmeticalFunctions(lastOperationInStack)(operand1, operand2)
- interpreterStack.Push(result)
- translatorStack.Push(inputOperation)
- End Sub
- Private f3 As Action(Of String) = Sub(inputOperation As String)
- translatorStack.Pop()
- End Sub
- Private f4 As Action(Of String) = Sub(inputOperation As String)
- Dim lastOperationInStack As String = translatorStack.Pop()
- Dim operand2 As Double = interpreterStack.Pop()
- Dim operand1 As Double = interpreterStack.Pop()
- Dim result As Double = arithmeticalFunctions(lastOperationInStack)(operand1, operand2)
- interpreterStack.Push(result)
- lastOperationInStack = translatorStack.Peek()
- transitionTable(VerticalIndexesMap(lastOperationInStack), HorizontalIndexesMap(inputOperation))(inputOperation)
- End Sub
- Private f5 As Action(Of String) = Sub(inputOperation As String)
- Throw New InvalidBracketsPlacementException("Incorrect placement of the brackets.")
- End Sub
- Private f6 As Action(Of String) = Sub(inputOperation As String)
- End Sub
- Private ReadOnly HorizontalIndexesMap As Dictionary(Of String, Int32) = New Dictionary(Of String, Int32)() From {
- {EmptyOperation, 0},
- {OpeningBracket, 1},
- {Plus, 2},
- {Minus, 3},
- {Multiplication, 4},
- {Division, 5},
- {ClosingBracket, 6}
- }
- Private ReadOnly VerticalIndexesMap As Dictionary(Of String, Int32) = New Dictionary(Of String, Int32)() From {
- {EmptyOperation, 0},
- {OpeningBracket, 1},
- {Plus, 2},
- {Minus, 3},
- {Multiplication, 4},
- {Division, 5}
- }
- Private ReadOnly transitionTable As Action(Of String)(,) = New Action(Of String)(,) {
- {f6, f1, f1, f1, f1, f1, f5},
- {f5, f1, f1, f1, f1, f1, f3},
- {f4, f1, f2, f2, f1, f1, f4},
- {f4, f1, f2, f2, f1, f1, f4},
- {f4, f1, f4, f4, f2, f2, f4},
- {f4, f1, f4, f4, f2, f2, f4}
- }
- ''' <summary>
- ''' Разделяет элементы выражения во входной строке пробелами.
- ''' </summary>
- Private Function PreprocessString(inputExpression As String) As String
- Dim resultExpression As String = ""
- inputExpression = String.Concat(inputExpression.Split(" "c))
- inputExpression = Multiplication + inputExpression
- 'Умножение в начале не попадет в итоговое выражение, использовано для предотвращения вылета за границы массива и корректной обработки унарных плюса/минуса в начале выражения.
- For i As Int32 = 1 To inputExpression.Length - 2
- Dim previousChar As Char = inputExpression(i - 1)
- Dim currentChar As Char = inputExpression(i)
- Dim nextChar As Char = inputExpression(i + 1)
- resultExpression += currentChar
- If NeedAddingSpace(previousChar, currentChar, nextChar) Then
- resultExpression += Space(1)
- End If
- Next
- resultExpression += inputExpression.Last
- Return resultExpression
- End Function
- ''' <summary>
- ''' Вспомогательная функция, проверяющая необходимость добавления пробела внутри тройки символов из входной строки.
- ''' </summary>
- Private Function NeedAddingSpace(previousChar As Char, currentChar As Char, nextChar As Char)
- If Char.IsDigit(currentChar) Then
- If Not Char.IsDigit(nextChar) Then Return True
- Else
- If currentChar = Minus Or currentChar = Plus Then
- If Not arithmeticalFunctions.ContainsKey(previousChar) Then Return True
- Else
- Return True
- End If
- End If
- Return False
- End Function
- Sub Main()
- Console.WriteLine("Enter arithmetic expression (space insensitive):")
- Try
- Console.WriteLine("Result: {0}",
- CalculateString(Console.ReadLine())
- )
- Catch invalidBracketsEx As InvalidBracketsPlacementException
- Console.WriteLine(invalidBracketsEx.Message)
- Catch ex As Exception
- Console.WriteLine("Error, invalid string.")
- End Try
- End Sub
- End Module
- Public Class InvalidBracketsPlacementException
- Inherits Exception
- Public Sub New()
- MyBase.New()
- End Sub
- Public Sub New(message As String)
- MyBase.New(message)
- End Sub
- End Class
Add Comment
Please, Sign In to add comment