C# 公式和数学表达式解析器算法
我必须写一个程序,能够解析公式。 它的工作原理如下所示: 输入:5x+7^sin(z)/2T+44C# 公式和数学表达式解析器算法,c#,algorithm,math,C#,Algorithm,Math,我必须写一个程序,能够解析公式。 它的工作原理如下所示: 输入:5x+7^sin(z)/2T+44 输出:输入x、z、t的值 输入:2,1,2 输出:答案是:某物 它应该支持(+、*、-、^、%,SIN,COS) 我确实读过关于调车场算法的那一页 我还知道如何将中缀表达式转换为后缀或前缀。 这是我的算法: 1-给出表达式2-如果 括号是平衡,请转至步骤3 否则显示错误转到步骤13- 查找除(SIN, COS)4-从 输入5-替换变量6 -为表达式添加前缀并计算它7-在输出中显示结果 并关闭
输出:输入x、z、t的值
输入:2,1,2
输出:答案是:某物
它应该支持(+、*、-、^、%,SIN,COS)
我确实读过关于调车场算法的那一页 我还知道如何将中缀表达式转换为后缀或前缀。
这是我的算法:
1-给出表达式
2-如果 括号是平衡,请转至步骤3 否则显示错误转到步骤1
3- 查找除(SIN, COS)
4-从 输入
5-替换变量
6 -为表达式添加前缀并计算它
7-在输出中显示结果 并关闭程序
是这样吗?我想在C#
中实现它,请告诉我任何对我有用的注意事项。我不知道如何在C#中实现它,但是python有一个非常强大的语法树分析器(ast模块),如果您将表达式作为python表达式给出,它可以在这里帮助您(这并不难,只需添加“*”乘法符号即可:-) 首先,定义只重新定义
visit\u Name
方法的好类(为标识符调用,例如为表达式调用另一个visit\u Expr
,visit\u Num
在满足数字时调用,等等,这里我们只需要标识符)
然后定义一个快速函数,该函数使用表达式为您提供其标识符:
>>> def visit(expression):
node = ast.parse(expression)
v = MyVisitor()
v.visit(node)
print v.identifiers
看起来还可以:
>>> visit('x + 4 * sin(t)')
['x', 't']
>>> visit('5*x + 7 ^ sin(z) / 2*T + 44')
['x', 'z', 'T']
将python 2.6或2.7用于ast模块。查看这些视频。这些视频都是C语言的,有很好的解释
如果你决定从头开始写,你的算法看起来不错。我将提供一些我的想法 您可能希望将步骤5(替换变量)移动到步骤6(为表达式添加前缀并进行计算)。换句话说,不只是对变量进行文本查找和替换,而是在计算过程中,在需要计算变量时进行查找和替换。这可能会在以后打开更多的可能性,可能会使绘制函数图或使用依赖于其他变量的值的变量变得更容易。不过,你的方法应该适用于简单的情况
sin
和cos
函数的一种可能实现方式是使用字典
,类似于:
private var functions =
new Dictionary<string, Func<double,double>>(StringComparer.OrdinalIgnoreCase)
{
{ "sin", Math.Sin },
{ "cos", Math.Cos },
{ "sec", Secant }
};
. . .
// checking whether a token is a defined function or a variable
if (functions.ContainsKey(token))
{
// determine the value of the argument to the function
double inputValue = getArgument();
double result = functions[token](inputValue);
. . .
}
. . .
private static double Secant(double x)
{
return 1.0 / Math.Cos(x);
}
专用变量函数=
新字典(StringComparer.OrdinalIgnoreCase)
{
{“sin”,数学,sin},
{“cos”,Math.cos},
{“秒”,正割}
};
. . .
//检查标记是已定义的函数还是变量
if(functions.ContainsKey(令牌))
{
//确定函数的参数值
double inputValue=getArgument();
双结果=函数[token](inputValue);
. . .
}
. . .
专用静态双正割(双x)
{
返回1.0/Math.Cos(x);
}
您可以使用ANTLR,请参见此。可能与
private var functions =
new Dictionary<string, Func<double,double>>(StringComparer.OrdinalIgnoreCase)
{
{ "sin", Math.Sin },
{ "cos", Math.Cos },
{ "sec", Secant }
};
. . .
// checking whether a token is a defined function or a variable
if (functions.ContainsKey(token))
{
// determine the value of the argument to the function
double inputValue = getArgument();
double result = functions[token](inputValue);
. . .
}
. . .
private static double Secant(double x)
{
return 1.0 / Math.Cos(x);
}