Click here to Skip to main content
15,886,067 members
Articles / Programming Languages / Visual Basic

Math Expression Evaluator

Rate me:
Please Sign up or sign in to vote.
2.90/5 (4 votes)
17 Aug 2006CPOL1 min read 35.6K   432   23   5
Calculate the result of a math expression.

Sample screenshot

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


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

Comments and Discussions

 
NewsLTFunctions Modification Pin
Jayke Huempfner8-Jun-11 17:31
Jayke Huempfner8-Jun-11 17:31 
GeneralUpdate: LTFunctions Modification Pin
Jayke Huempfner17-Feb-20 21:47
Jayke Huempfner17-Feb-20 21:47 
QuestionVariables Pin
Lutosław4-Oct-06 20:41
Lutosław4-Oct-06 20:41 
AnswerRe: Variables Pin
lucatabanelli4-Oct-06 22:00
lucatabanelli4-Oct-06 22:00 
AnswerRe: Variables Pin
hgrewa7-Feb-07 6:07
hgrewa7-Feb-07 6:07 
Checkout the expression evaluator that I am using in my unit converter application . It understand the variables for units in the given input. In addition, it also uses an auto complete feature that tells the user what variable (units in this case) are available for input.

Since library is designed to read the variables from external file (xml ) or sql database so variables can be easily removed or added for a given instance of the application. Later some day, I do plan to extend this to add physical constants since most of physical constants are not unit less so they must be defined in units so that expressions can be run on them (multiplication addition etc).


Grewal
http://www.mycoolaids.com

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.