Author: Admin 03/29/2021
Language:
Visual Basic .NET
Tags:
Evaluate a math expression entered in a text box.
here's sum code I found a few years back to evaluate a math expression entered in a text box.
Module MathExpression
Public m_Primatives As Hashtable
Public Enum Precedence
None = 11
Unary = 10 ' Not actually used.
Power = 9
Times = 8
Div = 7
IntDiv = 6
Modulus = 5
Plus = 4
End Enum
' Evaluate the expression.
Public Function EvaluateExpression(ByVal expression As String) As Double
Module MathExpression
Public m_Primatives As Hashtable
Public Enum Precedence
None = 11
Unary = 10 ' Not actually used.
Power = 9
Times = 8
Div = 7
IntDiv = 6
Modulus = 5
Plus = 4
End Enum
' Evaluate the expression.
Public Function EvaluateExpression(ByVal expression As String) As Double
Try
Dim expr As String
Dim is_unary As Boolean
Dim next_unary As Boolean
Dim parens As Integer
Dim expr_len As Integer
Dim ch As String
Dim lexpr As String
Dim rexpr As String
Dim status As Long = Nothing
Dim best_pos As Integer
Dim best_prec As Precedence
' Remove all spaces.
expr = expression.Replace(" ", "")
expr_len = Len(expr)
If expr_len = 0 Then Return 0
' If we find + or - now, it is a unary operator.
is_unary = True
' So far we have nothing.
best_prec = Precedence.None
' Find the operator with the lowest precedence.
' Look for places where there are no open
' parentheses.
For pos As Integer = 0 To expr_len - 1
' Examine the next character.
ch = expr.Substring(pos, 1)
' Assume we will not find an operator. In
' that case, the next operator will not
' be unary.
next_unary = False
If ch = " " Then
' Just skip spaces. We keep them here
' to make the error messages easier to
ElseIf ch = "(" Then
' Increase the open parentheses count.
parens += 1
' A + or - after "(" is unary.
next_unary = True
ElseIf ch = ")" Then
' Decrease the open parentheses count.
parens -= 1
' An operator after ")" is not unary.
next_unary = False
' If parens < 0, too many ')'s.
If parens < 0 Then
Throw New FormatException( _
"Too many close parentheses in '" & _
expression & "'")
End If
ElseIf parens = 0 Then
' See if this is an operator.
If ch = "^" Or ch = "*" Or _
ch = "/" Or ch = "\" Or _
ch = "%" Or ch = "+" Or _
ch = "-" _
Then
' An operator after an operator
' is unary.
next_unary = True
' See if this operator has higher
' precedence than the current one.
Select Case ch
Case "^"
If best_prec >= Precedence.Power Then
best_prec = Precedence.Power
best_pos = pos
End If
Case "*", "/"
If best_prec >= Precedence.Times Then
best_prec = Precedence.Times
best_pos = pos
End If
Case "\"
If best_prec >= Precedence.IntDiv Then
best_prec = Precedence.IntDiv
best_pos = pos
End If
Case "%"
If best_prec >= Precedence.Modulus Then
best_prec = Precedence.Modulus
best_pos = pos
End If
Case "+", "-"
' Ignore unary operators
' for now.
If (Not is_unary) And _
best_prec >= Precedence.Plus _
Then
best_prec = Precedence.Plus
best_pos = pos
End If
End Select
End If
End If
is_unary = next_unary
Next pos
' If the parentheses count is not zero,
' there's a ')' missing.
If parens <> 0 Then
Throw New FormatException( _
"Missing close parenthesis in '" & _
expression & "'")
End If
' Hopefully we have the operator.
If best_prec < Precedence.None Then
lexpr = expr.Substring(0, best_pos)
rexpr = expr.Substring(best_pos + 1)
Select Case expr.Substring(best_pos, 1)
Case "^"
Return _
EvaluateExpression(lexpr) ^ _
EvaluateExpression(rexpr)
Case "*"
Return _
EvaluateExpression(lexpr) * _
EvaluateExpression(rexpr)
Case "/"
Return _
EvaluateExpression(lexpr) / _
EvaluateExpression(rexpr)
Case "\"
Return _
CLng(EvaluateExpression(lexpr)) \ _
CLng(EvaluateExpression(rexpr))
Case "%"
Return _
EvaluateExpression(lexpr) Mod _
EvaluateExpression(rexpr)
Case "+"
Return _
EvaluateExpression(lexpr) + _
EvaluateExpression(rexpr)
Case "-"
Return _
EvaluateExpression(lexpr) - _
EvaluateExpression(rexpr)
End Select
End If
' If we do not yet have an operator, there
' are several possibilities:
'
' 1. expr is (expr2) for some expr2.
' 2. expr is -expr2 or +expr2 for some expr2.
' 3. expr is Fun(expr2) for a function Fun.
' 4. expr is a primitive.
' 5. It's a literal like "3.14159".
' Look for (expr2).
If expr.StartsWith("(") And expr.EndsWith(")") Then
' Remove the parentheses.
Return EvaluateExpression(expr.Substring(1, expr_len - 2))
Exit Function
End If
' Look for -expr2.
If expr.StartsWith("-") Then
Return -EvaluateExpression(expr.Substring(1))
End If
' Look for +expr2.
If expr.StartsWith("+") Then
Return EvaluateExpression(expr.Substring(2))
End If
' Look for Fun(expr2).
If expr_len > 5 And expr.EndsWith(")") Then
' Find the first (.
Dim paren_pos As Integer = expr.IndexOf("(")
If paren_pos > 0 Then
' See what the function is.
lexpr = expr.Substring(0, paren_pos)
rexpr = expr.Substring(paren_pos + 1, expr_len - paren_pos - 2)
Select Case lexpr.ToLower
Case "sin"
Return Math.Sin(EvaluateExpression(rexpr))
Case "cos"
Return Math.Cos(EvaluateExpression(rexpr))
Case "tan"
Return Math.Tan(EvaluateExpression(rexpr))
Case "sqrt"
Return Math.Sqrt(EvaluateExpression(rexpr))
Case "factorial"
Return Factorial(EvaluateExpression(rexpr))
' Add other functions (including
' program-defined functions) here.
End Select
End If
End If
' See if it's a primitive.
If m_Primatives.Contains(expr) Then
' Return the corresponding value,
' converted into a Double.
Try
' Try to convert the expression into a value.
Dim value As Double = _
Double.Parse(m_Primatives.Item(expr).ToString)
Return value
Catch ex As Exception
Throw New FormatException( _
"Primative '" & expr & _
"' has value '" & _
m_Primatives.Item(expr).ToString & _
"' which is not a Double.")
End Try
End If
' It must be a literal like "2.71828".
Try
' Try to convert the expression into a Double.
Dim value As Double = Double.Parse(expr)
Return value
Catch ex As Exception
Throw New FormatException( _
"Error evaluating '" & expression & _
"' as a constant.")
End Try
Catch ex As Exception
Return 0
End Try
End Function
' Return the factorial of the expression.
Public Function Factorial(ByVal value As Double) As Double
Try
Dim result As Double
' Make sure the value is an integer.
If CLng(value) <> value Then
Throw New ArgumentException( _
"Parameter to Factorial function must be an integer in Factorial(" & _
Format$(value) & ")")
End If
result = 1
Do While value > 1
result = result * value
value = value - 1
Loop
Return result
Catch ex As Exception
Return 0
End Try
End Function
End Module