Add your own alternative version
Stats
101.3K views 9.2K downloads 67 bookmarked
Posted
14 May 2012

Comments and Discussions


Is there a way to modify the MathParser.cs (in a "reasonable" way) to make it accept and validate the basic operators (+, , /, *) followed by + or ?
What I want: 2+2=0 OR 7*+3=+21
The only way I found to make it work: 2+(2)=0 OR 7*(+3)=+21





Heres the link:
MathParser
Think you may like it
I have Impletmented the following:
1. ObjectOrientation using Tokens
2. Support for Conditional Expressions
3. Scripting is being developed
4. Easily Define Variables, Operators, Functions even at Runtime
5. Value of Variables can be changed dynamically, even after a function is parsed and RPN is generated
6. RPN Caching for Reusable Expressions
7. Comma Seperated Parameter Lists for MultiArgument Functions
8. Support for TernaryFunctions
9. Support for PostfixFunctions like Factorial
10. AngleType Includes Grades
11. Predefined Combinatorial, Inverse and RoundOff Functions
12. Bypasses LexicalAnalysisRPN() , storing the RPN as as List<Token> instead of System.String for faster Evaluation
Mathew Sachin
modified 19Oct15 22:26pm.





please can add RPN export output, the I require for pasting into other applications such as calculators.
Thanks
por favor puede agregar exportar salida en RPN, la requiero para pegarla en otras aplicaciones como calculadoras.





i agree simple and fast.
i want to calculate for "999999999999.9999 * 999999999999.9999"
did you make source for decimal?





I found this code excellent and far simpler than other calculator code out there. I was able to compile it and add the dll to my main project in seconds. Someone mentioned variable substitution but I handle that in my front end. Works great!
But, my question is whether you can define multiargument functions. I created a Combinatorial function that I would like to call as comb(x,y), however, the parser thinks the comma is an operator and is thus failing. I can call it like (x comb y) or xcomb(y) but these aren't intuitive (the parentheses are of course required). It would be real nice if you could call it like {x y} using the braces to define the combinatorial. You would still need parentheses somewhere, but I'd settle for comb(x,y) for now. But what if there were 3 or more arguments?





I did find that this works: comb(7 (2))
As long as there are parentheses around either or both arguments it works.





This also works: Test((x) (y) z)





I have implemented Comma Support using by defining Comma as an Operator.
You can check my Comment for the complete source





Hi,
would it be possible that you integrate beside the parsing a conditional expression function.
For example: I would like to make some Decisions in my Application depending on values. In case
that "a > (b+c)" then return TRUE otherwise FALSE. In my case the app would translate the a,b,c into the following and sent it to the Parser: "5 >(3+4). In this case the Parser would return FALSE.
Do you get my point here. That function would be cool.





I Have implemented ConditionalExpressions and Much More:
Find it here





You can Write ur own parser in line whit dynamic expresions
ParameterExpression[] p1 = new ParameterExpression[] { };
var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(p1, typeof(bool), "2+3<4");
Console.WriteLine(e.Compile().DynamicInvoke()); ;
ParameterExpression[] p2 = new ParameterExpression[]
{Expression.Parameter(typeof(double), "x"),
Expression.Parameter(typeof(double), "y"),
Expression.Parameter(typeof(double), "z")};
var exprsion2 = System.Linq.Dynamic.DynamicExpression.ParseLambda(p2, typeof(bool), "x+y<z");
double x = 2, y = 3, z = 4;
Console.WriteLine(exprsion2.Compile().DynamicInvoke(x, y, z)); ;
You can even use to use Math.Sin(x) all u need to do to add Math.Sin(x) in string Magic^^,





I have been running the tests and see something wrong....
For example, in one of the tests part of the expression is 2*log(4) and for that particular term the author expects a result of 2 but 2 * log(4) = 1.204119.
Also, in the tests the Log function is invoked as Log(n) where n is a number yet if you look at the source code you see that the Log function uses TWO arguments in SyntaxAnalysisRPN.
http://www.coralys.com/
http://simulation.lordofwingsPTY.com/





OK, it would have been nice if there was more comments in the source code as not everybody is a mind reader Would also be nice if the demo project (the calculator) was packaged in the zip project, less complication.
Anyway, I am working in an Electrical Engineering application and needed to work with impedances (series, parallel) and something I greatly missed here was that it only dealt with numbers.
I spent some time with the sources (grateful to the author) and decided to make use of the System.Numerics.Complex type instead of a double. Unfortunately there is no common interface for numeric types so that one can transparently handle multitype.
I am still not done with it (time permitting), currently all numbers are promoted to Complex. So you
could do something like this:
Complex c = parser.Parse("(2.5+8.9i) * 5 / 2i");
Obviously when using explicit complex numbers in the formulas, one must take care of enclosing them with parenthesis to identify them as one, otherwise the multiplication/division would take precedence and do the operation with only part (real or imaginary) part. That's a limitation I can live for the moment.
However, I added another great feature and that is the introduction of a DeclareVariable() method which takes a double with an overload for a Complex.
parser.DeclareVariable("AR25", new Complex(5, 18));
parser.DeclareVariable("AN30", 356.0);
And now, having "declared" those variables to the parser instance I can parse an expression like this:
Complex c = parser.Parse("5 + 540 * AR25 / AN30");
during precalculation the variable references are converted to references to the declared variables and then during calculation that value is fetched and used.
I tried refactoring it to use a base class and then specializations for double and Complex but as it turned out it was too complicated introducing too much overhead.
Here are the preliminary results on my system:
Ticks (Co)Author Type Variables Remarks

72 Y. Kalzhani double N.A. Original without any modification
144 DEGT double 0 Enhanced but referencing zero variables
216 DEGT Complex 0 Enhanced but referencing zero variables
349 DEGT double 0 Enhanced using Generics but referencing zero variables
495 DEGT Complex 0 Enhanced using Generics but referencing zero variables
611 DEGT Complex 3 Enhanced using Generics using 3 double variables
611 DEGT Complex 3 Enhanced referencing 3 double variables
738 DEGT Complex 3 Enhanced using Generics using 3 double variables
858 DEGT Complex 4 Enhanced using Generics using 4 Complex variables
http://www.coralys.com/
http://simulation.lordofwingsPTY.com/
modified 5Feb15 14:52pm.





The only thing missing here is symbol transformation. Seldom do you just have numbers. For practical use you would at least have variables defined that you can then use in the expression.
Would be nice if you could define variables that are then dynamically replaced during evaluation. For example
A = 5
B = 10
A * B + 3 * (B  A)
which would then evaluate to 65.
http://www.coralys.com/
http://simulation.lordofwingsPTY.com/





I have implemented variable support
Here's the link





You have made a great job with this parser, if you have time I'd like to have mailing with you, my email address: jorgeham2000@gmail.com
Thanks
Jorge Ham







You did a quite good job with a really fast implementation. Your parser is well done in that direction! However, I wanted to compare your parser against one I wrote myself, and your parser had problems with more complicated strings, like
5268^16^5^72 17 89*24*37^24 58
Note that this is a autogenerated equation. Anyhow: decent job!





Thanks, but one moment, in an earlier version of the parser were analyzed and more complex lines, but they were illogical as those that you specify, a former math teacher convinced me to change my point of view about the convenience and consistency of such notation, so i change the parser and require parenthesis in expressions.





I know what you mean, however, you are always allowed to specify a standard, i.e. in
68^16^5^72
there is a standard defined (otherwise you need to use brackets). The standard is the same as
68^((16)^(5^72)).
One example of such a case is 2^2^2^2. If you go from left to right you end up with 256 (2^2 = 4, 4^2 = 16, 16^2 = 256). However, this case must be used as 2^2 = 4, 2^4 = 16, 2^16 = 65536. Compare with Google and Wikipedia  for powers if no bracket is specified the standard case must be right to left.
I solved this problem by not only preferring operations with higher orders, but also with the same order from the right side. This does not change ordinary operations like +,,... but it makes a difference in this edge case.
Anyway I see the problem and I consider it more advanced and not necessary for a math parser. I just wanted to point that out (the parser should maybe not crash  maybe report an error or hand back a result that might be valid from another point of view). As I stated before the performance of your parser is unmatched, so congratulations for that!





This is a commonly known topic: Operator Associativity[^]. Each decent math expression parser knows about this and makes proper decisions while parsing the passed expression string.
E.g. a<sup>b<sup>c</sup></sup> is rightassociative as described e.g. in Tetration[^].
Associativity says, where to start drawing parethesis if you have a chain of operators of the same Precedence[^].
The same holds for the unary + and  sign operator. And on more complex languages: casting, indexing, member access, etc. They are all rightassociative.
The vast majority of operators are leftassociative, as the standard math operators dictate.
All other interpretations are unexpected behaviour and misleading, i.e. violating one of the base rules of user interaction and programming (avoid unexpected/misleading/unintuitive behaviour).
Your argument to inhibit that is a bit awkward, since the rule is not discussable from a standard point of view (see http://en.wikipedia.org/wiki/Tetration[^]).
Cheers
Andi





The expression is not illogical. The only problem is the numbers used in the exponents are far to large to be held in a double. Make them smaller like below and then you can evaluate it.
522^2^2^21789*24*37^2458
The answer is 9.2564109e+40.





All I see in the code section is exe's. Not very useful





it`s demo app in section Browse code, its because i update my article and file MathParserTK, which have source code (updated only comments in code) and deleted old file with source code, my newer version of this article with source code is pending





Hi,
Have you seen my Sym project at sym.codeplex.com? It transforms algebraic equations and solves.
SymbolicComputation.com





yes, i saw it, good project, good luck





Could you update your image links, please? They are not working. (At least on my box)
I wasn't, now I am, then I won't be anymore.





I fixed it thanks for the post





Please show and explain the code.





Hi, just download zipfile MathParserTK_1_1 (i updated it), in file mathParserTK.cs I tried to explain the work of the parser code in the comments and how it can be changed.





Very few people here will download code sight unseen. Especially if it's just to see how it's done. Show and explain the code and if someone wants to use it he may download it.





Hello kirnbas,
your evaluator solution seems to me quite verbose and overcomplicated.
You might have a look at Mathematical Expression Parser Using Coco/R[^] which provides two solutions:
A) writing a similar evaluator in about 100 lines of code by using http://ssw.jku.at/Coco/[^]
B) writing the same evaluator, but hand crafted, in less than 150 lines of code
BTW: I also find that you should elaborate more on why you show us your trick  why should I red that? E.g. if talking about localized number scheme, then you must talk about the consequences and how you deal with these:
 What number formats exist (decimal point, thousand separator, ...)?
 How you deal with the ambiguities (you have to also localize the list separator)?
 Run the localization on kkKZ, kyKZ, enUS, deDE, deCH, svSE, svFI
The quirks on localization is that the coma is usually used as list separator (e.g. f(a,b) ) as well as thousand separator (enUS) or as decimal separator (deDE).
One approach is to allow the ambiguity and let the parser read greedily (letting the user to solve ambiguities by adding parenthesis, e.g. f((3,14159),(1,4142135)) ).
Another approach is to make the language not ambiguous and also take the list separator from the CultureInfo class (beside the thousand separator and the decimal separator).
At least this topic is worth an elaboration. That's why my vote of 3.
Cheers
Andi





You might want to elaborate on some of the inner workings, etc. This is extremely short for an article.






General News Suggestion Question Bug Answer Joke Praise Rant Admin Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

