Evaluate a simple string equation

I would like to be able to build a small string which will be evaluated as a mathematical calculation

all evaluation will always be formatted in this manner.
number operator number operator number operator number.

The only operators used are the basic  + - / * set.

There will be a high volume of calculations producing every combination.  The results will be listed as either meeting a predefined result or not.

The project is based around an alternative  encryption model I have been considering for sometime.
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

This is not a question. So it is very difficult to provide an answer to you. What do you need?
Fernando SotoRetiredCommented:
And the question is?
AlyantoAuthor Commented:
Well the question is:  How to evaluate a string as a mathematical formula.  
How and which how is the best is the question?  

I had thought the first sentence aluded to the question.
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

Fernando SotoRetiredCommented:
Well there is no class in C# that will dynamically parse a math string / equation  and and calculate the results. So that means you will need to code it. Please see this article on the subject, CodeDom Calculator - Evaluating C# Math Expressions Dynamically.
Julian HansenCommented:
The standard way of doing this is by using operator precedence and operator + operand stacks.

First tokenise the string (in your case splitting the string on spaces would do).

Walk through the array and push operators on the operator stack and operands on the operand stack.

When pushing an operator
Check the precedence of the operator (* / has higher precedence than - +) being pushed with the top operator on the stack
  - if the stack top is higher then
      pop the top of the operator stack and the top two operands from the operand stack.
      Perform the operation and push the result back on the operand stack
      Repeat the above process until the top of the operator stack is less than or equal to the new operator - at which point push the new.

When you have run out of tokens loop through the process of popping two operands and an operator and pushing the result to the operand stack until both stacks are empty - you will now have your result.
Ess KayEntrapenuerCommented:
Here is the solution:

You can have a go at this : http://www.codeproject.com/vb/net/math_expression_evaluator.asp

Alternitavely try this code

Public Class Calculations 'don't forget to add "Imports System.Text.RegularExpressions" in the top
    Private Shared ReadOnly CalcOrder As String = "^*/+-" 'represents the order of calculations 
    Private Shared ReadOnly nOperatorUB As Integer = CalcOrder.Length - 1
    Private Shared ReadOnly rxBrackets As New Regex("\((.+)\)", RegexOptions.Compiled)
    Private Shared ReadOnly AllowedCharacters As String = "().,1234567890 " & CalcOrder 'hope I didn't miss any 
    Private Shared ReadOnly rxCheck As New Regex("^[" & AllowedCharacters & "]+$", RegexOptions.Compiled)
    Private Shared ReadOnly rxOperators() As Regex

    Shared Sub New()
        'sub will only run once when class is first accessed (shared) to prevent bottleneck performance
        Const exprform As String = "(\d+(?:[.,]\d+)?) *(\%%%) *([+-]?\d+(?:[.,]\d+)?)"
        Dim i As Integer
        'create a different compiled regular expression for each operator to ensure performance
        ReDim rxOperators(nOperatorUB)
        For i = 0 To nOperatorUB
            rxOperators(i) = New Regex(exprform.Replace("%%%", CalcOrder.Substring(i, 1)), System.Text.RegularExpressions.RegexOptions.Compiled)
    End Sub

    'Private Shared ReadOnly rxFormula As New System.Text.RegularExpressions.Regex("(?<number>[+-]?\d+(?:[.,]\d+)?)(?<operator>[^\d]+)?", Text.RegularExpressions.RegexOptions.Compiled)
    'NB: uses local settings for decimal seperators. 
    Public Shared Function EvaluateFormula(ByVal Formula As String) As Double
        Return EvaluateFormula(Formula, 6)
    End Function
    Public Shared Function EvaluateFormula(ByVal Formula As String, ByVal Precision As Integer) As Double

        'replace E xponential with the proper syntax 
        Formula = Formula.Replace("e"c, "E"c).Replace("E", "*10^")

        'fase one: checks (if you're sure all formulas are valid you could remove this part)
        'check for invalid characters 
        If Not rxCheck.IsMatch(Formula) Then
            Throw New Exception("Invalid formula: " & Formula)
        End If

        'check for number of () If they're not equal raise error 
        If Formula.Replace("("c, Nothing).Length <> Formula.Replace(")"c, Nothing).Length Then
            Throw New Exception("Unequal amount of ()")
        End If

        'step 2: all code between brackets
        Dim m As Match, res As Double, prec As String = "0." & New String("0"c, Precision)
            m = rxBrackets.Match(Formula)
            If Not m.Success Then Exit Do
            res = EvaluateFormula(m.Groups(1).ToString(), Precision)
            Formula = Formula.Replace(m.ToString(), res.ToString(prec))

        'step 2 operators
        Dim rx As Regex, N1, N2 As Double
        For Each rx In rxOperators
                m = rx.Match(Formula)
                If Not m.Success Then Exit Do
                N1 = Double.Parse(m.Groups(1).ToString())
                N2 = Double.Parse(m.Groups(3).ToString())

                Select Case Char.Parse(m.Groups(2).ToString)
                    Case "^"c
                        res = N1 ^ N2
                    Case "*"c
                        res = N1 * N2
                    Case "/"c
                        res = N1 / N2
                    Case "+"c
                        res = N1 + N2
                    Case "-"c
                        res = N1 - N2
                End Select
                If m.ToString().Length = Formula.Length Then Return res
                Formula = Formula.Replace(m.ToString(), res.ToString(prec))
        Return Double.Parse(Formula)
    End Function

End Class

        Dim i As Integer, now As DateTime = DateTime.Now, res As Double
        Console.WriteLine("Start ")
        For i = 0 To 10000
            res = Calculations.EvaluateFormula("5 * 20 / " & i.ToString)
        Console.WriteLine("Finished. duration: " & DateTime.Now.Subtract(now).ToString)
        '10000 iterations finished in a matter of seconds. 100000 still took about 15 secs. though

Open in new window


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
AlyantoAuthor Commented:
Thank you for the solution, I finally got the opportunity to try it out this morning and I am really pleased with it.  Cheers A***
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.