1

I am new to C#, and don't have a big scale of options to do specific tasks. But still have the challenge to create a scientific calculator.

What I want to get is separating a parent, with start and end tag from a child. Also count how many parents and the order which parent is first and then and then and so on.

With the content of each child. After that I calculate the results of each child (if there is any) and create the content of the parent which get calculated too.

for example:

string somestring = "5+5+(3+1+(0+1))+5+5+(3+1+(0+1))";

and from the calculated result (example is in javascript but I want it in C#):

result = 
[{
    "parent" : "content of parent",
    "child" : ["content of child","content of child"]
},
{
    "parent" : "content of parent",
    "child" :["content of child","content of child","content of child"]
}];

this way I can :

  • count length of 'result' array to get number of parents.
  • count length of 'child' array to get number of children.
  • get the content of the element by pointing to the array index number.

It doesn't have to be in this type of array, but some way to do the things above.

Thanks for your time and help!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Ismail
  • 8,904
  • 3
  • 21
  • 39

4 Answers4

3

What you are looking for is called the Shunting-yard algorithm. The Wikipedia page provides a nice explaination on the algorithm. Also, I wrote an article and a C# program to do this for you called Math Parser .NET. In addition, the library will allow you to define your own functions for virtually anything!

In addition, I also wrote a tokenizer program to automatically generate C# or VB.NET code based on input that will tokenize your input for you! This is useful if you need to write your own math parser and just need a tokenizer to get you started.

Icemanind
  • 47,519
  • 50
  • 171
  • 296
2

If you want to evaluate it on your own, you'll need to create a binary tree.

For the parent node, you would give it: 5+5+(3+1+(0+1))+5+5+(3+1+(0+1)) Then it would create two child nodes

.  [+]
.  /  \
.[5]  [5+(3+1+(0+1))+5+5+(3+1+(0+1))]

The left part is ok. The right part now need to be splitted

.  [+]
.  /  \
.[5]  [(3+1+(0+1))+5+5+(3+1+(0+1))]

The left part is ok. The right part now need to be splitted

.            [+]
.  /                 \
.[(3+1+(0+1))]  [5+5+(3+1+(0+1))]

Both part need to be splitted

.      [+]
.  /        \
.[(3+1)]  [(0+1)]

and continue like this

You would end up with.

.  [+]
.  /  \
.[5]  [+]
.     /  \
.    [5]  [+]
.         /  \
.      [+]  [...]
.     /   \
.   [+]    [+]
.  /  \    /  \
.[3] [1]  [0] [1]

That way it's easy to evaluate the result, find parents and childs.

More info: http://en.wikipedia.org/wiki/Binary_expression_tree

the_lotus
  • 12,668
  • 3
  • 36
  • 53
1

If you are trying to parse that string and then calculate it's value this is not a valid answer for you, but if your main goal is to calculate value of a given string you may use DataTable.Compute method.

It's really easy to calculate with that function, you may check out this answer given at stackoverflow.

var result = new DataTable().Compute("2-3/4*12", null);

I hope you do not use regular expressions for that.

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.

Community
  • 1
  • 1
Ahmet Kakıcı
  • 6,294
  • 4
  • 37
  • 49
  • I could also use the .dll from Ncalc (http://ncalc.codeplex.com/), but I want to learn to create it myself but not have some kind of build in plugin. – Ismail Nov 21 '13 at 18:05
0

You can use lexer+parser (generator) for C# to build expression tree. I wrote NLT suite and you have good starter there included in examples (see number 4 -- calculator). It is not scientific, but it is a matter of adding pieces you want. To give you the feel how it works, this is lexer section (key parts):

"(" -> LPAREN;
")" -> RPAREN;
"+" -> PLUS;
"-" -> MINUS;
"*" -> MULT, SymbolEnum.MULT; // make the Value equal to MULT as well
"/" -> DIV;
"^" -> POWER;

// regex as pattern
/[0-9]+/ {
            $token = SymbolEnum.NUM;
            $value = Convert.ToDouble($text);
     };

" " { };

"#" { lexer.PushState(StatesEnum.COMMENT); };
COMMENT /./ { };

/./ -> Error;

%EOF -> EOF;

Parsing is shorter:

s -> e:exp { e };

exp -> LPAREN e:exp RPAREN
       { e }
     | e1:exp PLUS e2:exp
           { new AstNode(SymbolEnum.PLUS, e1, e2) }
     | e1:exp MINUS e2:exp
           { new AstNode(SymbolEnum.MINUS, e1, e2) }
     | e1:exp tok:MULT e2:exp
           { new AstNode((SymbolEnum)tok, e1, e2) }
     | e1:exp DIV e2:exp
           { new AstNode(SymbolEnum.DIV, e1, e2) }
     | e1:exp POWER e2:exp
           { new AstNode(SymbolEnum.POWER, e1, e2) }
     | n:NUM
           { new AstNode(n) }
     | LPAREN Error RPAREN
           // no code
     ;
greenoldman
  • 16,895
  • 26
  • 119
  • 185