15,799,398 members
Articles / Programming Languages / Visual Basic

# Math Expression Evaluator

Rate me:
18 Aug 2006CPOL1 min read 35.4K   432   23   5
Calculate the result of a math expression.

## Introduction

This is another math expression evaluator with which you can let the user type an expression in text format with up to three variables (x, y, z) and calculate the result according to the variable values.

## The main idea

Parse the text function and build a tree-like structure because a math expression is always an operator with "something" left and "something" right. "something" can be a variable or a number or an expression itself. Functions like sin, cos... are special nodes whose argument is an expression. Simple, isn't it?

For example: 2*x - 4/sin(3*x) according to the operator precedence is a subtraction, if we build a tree like this...

```                  -----
|  -  |
-----
_______|  |  |_______
|        -----        |
-----                 -----
|  *  |               |  /  |
-----                 -----
_|  |  |_             _|  |  |_
|  -----  |           |  -----  |
-----     -----       -----     -----
|  2  |   |  X  |     |  4  |   | sin |
| nr. |   | var |     | nr. |   |-----|
-----     -----       -----    |     |
--|--
|
-----
|  *  |
-----
_|  |  |_
|  -----  |
-----     -----
|  3  |   |  X  |
| nr. |   | var |
-----     -----```

... we can read the original expression by scanning the tree from left to right.

## Building the tree

Each type of node (operator, operand, function) is implemented by a proper class.

VB
```Private Class clsFunction
Protected mName As String
Protected mArgument As Object
Public Sub New()
mName = ""
mArgument = Nothing
End Sub
Property Name() As String
Get
Return mName
End Get
Set(ByVal Value As String)
mName = Value
End Set
End Property
Property Argument() As Object
Get
Return mArgument
End Get
Set(ByVal Value As Object)
mArgument = Value
End Set
End Property
End Class

Private Class clsOperator
Protected mOperator As String
Protected mLeft As Object
Protected mRight As Object
Public Sub New()
mLeft = Nothing
mRight = Nothing
End Sub
Property Operator() As String
Get
Return mOperator
End Get
Set(ByVal Value As String)
mOperator = Value
End Set
End Property
Property Left() As Object
Get
Return mLeft
End Get
Set(ByVal Value As Object)
mLeft = Value
End Set
End Property
Property Right() As Object
Get
Return mRight
End Get
Set(ByVal Value As Object)
mRight = Value
End Set
End Property
End Class

Private Class clsOperand
Protected mIsVariable As Boolean
Protected mVariable As String
Protected mOperand As Decimal
Property IsVariable() As Boolean
Get
Return mIsVariable
End Get
Set(ByVal Value As Boolean)
mIsVariable = Value
End Set
End Property
Property Variable() As String
Get
Return mVariable
End Get
Set(ByVal Value As String)
mVariable = Value
End Set
End Property
Property Operand() As Decimal
Get
Return mOperand
End Get
Set(ByVal Value As Decimal)
mOperand = Value
End Set
End Property
End Class```

We build the expression tree according to the operator precedence this way:

• Function `Expression` handles left sum|sub right by calling the function `Term` for each side.
• Function `Term` handles left mult|div right by calling the function `Factor` for each side.
• Function `Factor` handles left power right by calling the function `Power` for each side.
• Function `Power` ends the work by detecting a new expression (if brackets), function (3 letters), variable, or number.

## Calculate the result

Once we have the tree, scanning it from left to right to calculate the result is quite simple:

VB
```Protected Overridable Function GetResult(ByVal objNode As Object) As Decimal
'calculate the result of the function in terms of x,y,z
'by recursively scanning the tree from left to right

If objNode Is Nothing Then Return 0

If TypeOf objNode Is clsFunction Then
Select Case objNode.Name.ToLower
Case "sin"
Return System.Math.Sin(GetResult(objNode.Argument))
Case "cos"
Return System.Math.Cos(GetResult(objNode.Argument))
Case "tan"
Return System.Math.Tan(GetResult(objNode.Argument))
Case "atn"
Return System.Math.Atan(GetResult(objNode.Argument))
Case "lne"
Return System.Math.Log(GetResult(objNode.Argument))
Case "log"
Return System.Math.Log10(GetResult(objNode.Argument))
Case "sqr"
Return System.Math.Sqrt(GetResult(objNode.Argument))
End Select
ElseIf TypeOf objNode Is clsOperator Then
Select Case objNode.operator
Case "+"
Return GetResult(objNode.Left) + GetResult(objNode.Right)
Case "-"
Return GetResult(objNode.Left) - GetResult(objNode.Right)
Case "*"
Return GetResult(objNode.Left) * GetResult(objNode.Right)
Case "/"
Return GetResult(objNode.Left) / GetResult(objNode.Right)
Case "^"
Return GetResult(objNode.Left) ^ GetResult(objNode.Right)
End Select
ElseIf objNode.isvariable Then
Select Case objNode.variable
Case "X"
Return mX
Case "Y"
Return mY
Case "Z"
Return mZ
End Select
Else
Return objNode.operand
End If
End Function```

See the source code for more comments.

## Using the code

VB
```dim LtFn as New LTFunctions.Functions
With LtFn
.Function = "sin(x)+2*p"
.X =-1
.Y = 0
.Z = 0
Messagebox.Show (Format(.Result, "standard"))
End With```

Written By
Web Developer
Italy
VB.NET developer since it was born