我是C#的新手,没有大量选项来完成特定任务。但仍然面临着创建科学计算器的挑战。
我想要的是将父项与子项的开始和结束标记分开。还要计算父母的数量和父母先后的顺序,然后等等。
随着每个孩子的内容。之后,我计算每个孩子的结果(如果有的话),并创建计算得到的父母的内容。
例如:
string somestring = "5+5+(3+1+(0+1))+5+5+(3+1+(0+1))";
并从计算结果(例如在javascript中,但我希望它在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"]
}];
这样我可以:
它不一定是这种类型的数组,而是某种方式来做上述事情。
感谢您的时间和帮助!
答案 0 :(得分:3)
您正在寻找的是Shunting-yard algorithm。维基百科页面提供了对算法的很好的解释。另外,我写了一个article and a C# program来为你做这个叫做Math Parser .NET。此外,该库允许您为几乎任何东西定义自己的功能!
此外,我还编写了a tokenizer程序,根据输入自动生成C#或VB.NET代码,为您输入令牌!如果您需要编写自己的数学解析器并且只需要一个tokenizer来帮助您入门,这非常有用。
答案 1 :(得分:2)
如果您想自己评估它,您需要创建一个二叉树。
对于父节点,您可以给它:5 + 5 +(3 + 1 +(0 + 1))+ 5 + 5 +(3 + 1 +(0 + 1)) 然后它会创建两个子节点
. [+]
. / \
.[5] [5+(3+1+(0+1))+5+5+(3+1+(0+1))]
左边部分没问题。现在需要拆分正确的部分
. [+]
. / \
.[5] [(3+1+(0+1))+5+5+(3+1+(0+1))]
左边部分没问题。现在需要拆分正确的部分
. [+]
. / \
.[(3+1+(0+1))] [5+5+(3+1+(0+1))]
这两个部分都需要拆分
. [+]
. / \
.[(3+1)] [(0+1)]
并继续这样
你最终会得到。
. [+]
. / \
.[5] [+]
. / \
. [5] [+]
. / \
. [+] [...]
. / \
. [+] [+]
. / \ / \
.[3] [1] [0] [1]
通过这种方式,您可以轻松评估结果,找到父母和孩子。
答案 2 :(得分:1)
如果您尝试解析该字符串然后计算它的值,那么不是您的有效答案,但如果您的主要目标是计算a的值给定字符串,您可以使用DataTable.Compute方法。
使用该函数计算非常简单,您可以查看stackoverflow中给出的this answer。
var result = new DataTable().Compute("2-3/4*12", null);
我希望你不要使用正则表达式。
有些人在遇到问题时会想“我知道,我会用 正则表达式。“现在他们有两个问题。
答案 3 :(得分:0)
您可以使用lexer + parser(generator)为C#构建表达式树。我写了NLT套件,你在示例中包含了很好的启动器(参见数字4 - 计算器)。它不科学,但它是一个添加你想要的东西的问题。为了让您了解它是如何工作的,这是词法分析部分(关键部分):
"(" -> 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;
解析时间较短:
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
;