The first term you need to know when you are trying to evaluate expressions is "tokenize". It means splitting into simpler parts. For example, "12+5*3" is tokenized to "12","+","5","*", and "3".

Before tokenizing, I thought I would do some substitutions to make it simpler for the programmer.

First, we should remove all the spaces to avoid errors like "Cannot convert " " to Double".

Secondly, treating '-' as an operator might lead to few a complications because when you have expressions like "5*-5", the logic we have provided here will get complicated. So, to support negative numbers with our simple logic, the easiest workaround would be replacing all instances of the form "number-number" with "number+-number". While tokenizing, we write a logic such that the - sign is also concatenated to the string.

We use Regex to do this. I will explain about it later.

Then, I replace functions with symbols. For example, the trigonometric function Sine is replaced with "~". So, when I want to evaluate the expression, I can recognize the "~" symbol and evaluate Sine (the number following it). How I'm doing it will be mentioned in the explanation of the evaluation part.

Then, I replace PI and e with their respective values rounded to 4 decimal digits. One thing to be noticed here is, the user might accidentally type "Pi" or "pI" or "PI". So, in order to handle substitutions in general, better use the LCase function and search for the replacement string ("pi" in this case) in lower case.

The logic I've been mentioning all along is:

Read character by character in the expression.

If the character is a number or a dot or a '-' sign or a symbol denoting a function (like "~" for sine), concatenate it to a string.

If it is an operator, add the number to a list followed by the operator. Set the values of the number string and the operator string to be "".

After the loop is over, add the number in the string (num in this case) to the list because there will be no operator in the end.

Then, clear the ListBox tokens and add all the entries in the list (tokens in this case) so that the user can see how it is tokenized. It is not necessary to include the ListBox in all expression evaluators. This is just to see if the program properly tokenizes the expression.

Coming back to RegEx or Regular Expressions, one can say that it is very useful in pattern matching. Here, the pattern we are trying to match is of the form "a numerical digit-a numerical digit". Let's take the expression "12-3+15-4".

The matches returned by Regex will be "2-3" and "5-4". Then, we can replace it with "2+-3" and "5+-4" so that we can tokenize (split into parts) the expression as "12","+","-3","+","15","+", "-4" and then evaluate it.

In the declaration of x, I have given "[0-9]\-[0-9]" as the pattern string. This pattern string is what the regex finds as matches. The pattern string here means "any digit from zero to nine-any digit from zero to nine". One or more characters within the "[]" will be matched, and the "\-" means, - should be treated as a "-" character and not as what it is meant to be in the Regex syntax. Normally, "-" is used inside "[]" to denote a range like "0-9", or "a-z", or "A-Z". "\" is called an escape sequence that forces the next character to be treated as a literal.

This function is for evaluating strings like "~30"(sin 30) etc. As I have already mentioned, the symbols I have used will always be present in the first character of the string. So, I check if the first character of the string (s here) passed is a symbol in that list. If it is not, I return the same string passed as it is. On the other case, I retrieve the number part using the substring function and convert it to degrees. The trigonometric functions will treat the value passed as radians. So, I convert the number to degrees. The conversion is like direct proportion. PI Radians equal 180 degrees. How many degrees equal z radians?

z = z * PI/180

Then, the respective function is performed on z and is returned by checking all possible symbols that can be present as the first character of s.

About the Author

Comments and Discussions

I for one am impressed that someone who from appearances must be pretty young, understands tokenization and can build an expression evaluator of any kind.

Good job! Keep working and learning and you will get better and better at it. There are better ways of tokenization and of course you can allow for parenthesis, by using reverse polish notation and/or a stack, but this is a good start.

Oh! Thank you for the suggestion. I've already done another expression evaluator that supports parenthesis and functions like gcd,lcm,median etc.

I've been trying to include equation solving which forces me to include support for complex numbers. So, is it all right if I upload the version without the equation solver and post another along with the equation solver once I'm done with it?