Click here to Skip to main content
Licence CPOL
First Posted 17 Aug 2006
Views 20,244
Downloads 202
Bookmarked 21 times

Math Expression Evaluator

By | 17 Aug 2006 | Article
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.

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:

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

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)

About the Author

lucatabanelli

Web Developer

Italy Italy

Member

VB.NET developer since it was born

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
NewsLTFunctions Modification PinmemberJayke Huempfner17:31 8 Jun '11  
QuestionVariables Pinmembergajatko20:41 4 Oct '06  
AnswerRe: Variables Pinmemberlucatabanelli22:00 4 Oct '06  
AnswerRe: Variables Pinmemberguyinfun6:07 7 Feb '07  

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

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

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120517.1 | Last Updated 18 Aug 2006
Article Copyright 2006 by lucatabanelli
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid