|
Thank you so much for the time and effort you put in this masterpiece!
I have been working on the same thing and just discovered your solution.
My parser was already completely working, but only supporting
()-Expressions and basic operators +,-,*,/
Thank you so much!
|
|
|
|
|
The Arpian math evaluator does seem very powerful and an improvment over this. However I found that it requires C# v6 and using Unity it would not work for me.
But I DID want to support the syntax min(x,y) rather than (x)min(y) or min(x(y)) so I added a comma operator as follows
else if ( token == Comma )
{
stack.Push( LeftParent );
commaParen++;
}
else if ( token == RightParent )
{
string elem;
while ( commaParen > 0 )
{
while ( ( elem = stack.Pop() ) != LeftParent )
outputString.Append( elem );
commaParen--;
}
while ( ( elem = stack.Pop() ) != LeftParent )
outputString.Append( elem );
if ( stack.Count > 0 && stack.Peek()[0] == FunctionMarker[0] )
{
outputString.Append( stack.Pop() );
}
}
|
|
|
|
|
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 19-Oct-15 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 multi-argument 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 multi-type.
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 pre-calculation 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 5-Feb-15 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 e-mail 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
52-68^-16^5^72 -17 -89*-24*-37^24 -58
Note that this is a auto-generated 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 right-associative 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 right-associative.
The vast majority of operators are left-associative, 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.
52-2^-2^2^2-17-89*-24*-37^24-58
The answer is -9.2564109e+40.
|
|
|
|