strExpression = "1+2+3"
Say I have an expression written in a string. Is there some way that can be
evaluated? Order of precedence does not matter, it should just go from left
to right.
I had an idea using arrays. I figured I could make two arrays, one for the
numbers, one for the operands. It would look at the first two numbers in the
NumberArray, and do the math based on the first operand in the OperandArray.
Then it would take that total, and use it against the third number doing the
math of the next operand, etc. It would work, but I have a problem with this
too. Of what type are operands? My NumberArray is a decimal array. I have no
idea what to make my OperandArray.
So maybe that idea isn't possible. If anyone could help me with either
method that would be great! Either converting a string expression into a
mathematical expression that can be calculated, or how to make an array to
hold *usable* operands.
Thanks!
I wrote this simple class for evaluating expressions. I'm sure it
could use some improvements but perhaps it can help you::
Public Class SimpleEval
Private Shared _operators() As String = {"-", "+", "/", "*", "^"}
Private Shared _operations() As Func(Of Double, Double, Double) =
{Function(a1, a2) a1 - a2, Function(a1, a2) a1 + a2, Function(a1, a2)
a1 / a2, Function(a1, a2) a1 * a2, Function(a1, a2) a1 ^ a2}
Public Shared Function Eval(ByVal expression As String) As Double
Dim tokens As List(Of String) = getTokens(expression)
Dim operandStack As New Stack(Of Double)
Dim operatorStack As New Stack(Of String)
Dim tokenIndex As Integer = 0
While tokenIndex < tokens.Count
Dim token As String = tokens(tokenIndex)
If token = "(" Then
Dim subExpr As String = getSubExpression(tokens,
tokenIndex)
operandStack.Push(Eval(subExpr))
Continue While
End If
If token = ")" Then
Throw New ArgumentException("Mis-matched parentheses
in expression")
End If
If Array.IndexOf(_operators, token) >= 0 Then 'If this
is an operator
While operatorStack.Count > 0 AndAlso Array.IndexOf
(_operators, token) < Array.IndexOf(_operators, operatorStack.Peek())
Dim op As String = operatorStack.Pop()
Dim arg2 As Double = operandStack.Pop()
Dim arg1 As Double = operandStack.Pop()
operandStack.Push(_operations(Array.IndexOf
(_operators, op))(arg1, arg2))
End While
operatorStack.Push(token)
Else
operandStack.Push(Double.Parse(token))
End If
tokenIndex += 1
End While
While operatorStack.Count > 0
Dim op As String = operatorStack.Pop()
Dim arg2 As Double = operandStack.Pop()
Dim arg1 As Double = operandStack.Pop()
operandStack.Push(_operations(Array.IndexOf(_operators,
op))(arg1, arg2))
End While
Return operandStack.Pop()
End Function
Private Shared Function getSubExpression(ByVal tokens As List(Of
String), ByRef index As Integer) As String
Dim subExpr As New StringBuilder()
Dim parenlevels As Integer = 1
index += 1
While index < tokens.Count AndAlso parenlevels > 0
Dim token As String = tokens(index)
If tokens(index) = "(" Then
parenlevels += 1
End If
If tokens(index) = ")" Then
parenlevels -= 1
End If
If parenlevels > 0 Then
subExpr.Append(token)
End If
index += 1
End While
If (parenlevels > 0) Then
Throw New ArgumentException("Mis-matched parentheses in
expression")
End If
Return subExpr.ToString()
End Function
Private Shared Function getTokens(ByVal expression As String) As
List(Of String)
Dim operators As String = "()^*/+-"
Dim tokens As New List(Of String)()
Dim sb As New StringBuilder()
For Each c As Char In expression.Replace(" ", String.Empty)
If operators.IndexOf(c) >= 0 Then
If (sb.Length > 0) Then
tokens.Add(sb.ToString())
sb.Length = 0
End If
tokens.Add(c)
Else
sb.Append(c)
End If
Next
If (sb.Length > 0) Then
tokens.Add(sb.ToString())
End If
Return tokens
End Function
End Class
Chris