公式和数学表达式解析算法

本文关键字:算法 表达式 | 更新日期: 2023-09-27 17:51:22

我必须编写一个能够解析公式的程序。它应该像下面的例子一样工作:

输入:5x + 7 ^ sin(z)/2T + 44
输出:输入x, z, t的值
输入:2、1、2
输出:答案是:something


应该支持(+,*,-,^,%,SIN, COS)
我确实读过分流码算法这一页

我也知道如何将中缀表达式转换为后缀或前缀。
这是我的算法:

1 -给出表达式。
2 -如果括号是平衡转到步骤3否则显示错误,转到步骤1
3 -求除(SIN)之外的所有变量,COS)
4 -从输入
5 -替换变量
6-在表达式前加上前缀并计算
7 -在输出中显示结果并关闭程序

对吗?我想在c#中实现它
请给我建议任何可能对我有用的注释

公式和数学表达式解析算法

如果您决定从头开始编写,那么您的算法看起来不错。我将提供一些我的想法。

您可能希望将步骤5(替换变量)移动到步骤6(为表达式添加前缀并计算它)。换句话说,不只是对变量进行文本查找和替换,而是在需要计算变量时进行计算。这可以在以后打开更多的可能性,可能更容易绘制函数或具有依赖于其他变量的值的变量。不过,您的方法应该适用于简单的情况。

sincos函数的可能实现,使将来更容易定义其他函数,可以有一个Dictionary<string, Func<double,double>>,类似于:

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);
}

我不知道如何在c#中做到这一点,但是python有一个非常强大的语法树分析器(ast模块)可以在这里帮助你,如果你把表达式作为python表达式(这并不难,你只需要添加'*'乘法号:-))。

首先,定义只重新定义visit_Name方法的好类(为标识符调用,例如另一个visit_Expr为表达式调用,visit_Num在满足数字时调用,等等,这里我们只想要标识符)。

>>> import ast
>>> class MyVisitor(ast.NodeVisitor):
    def __init__(self, *args, **kwargs):
        super(MyVisitor, self).__init__(*args, **kwargs)
        self.identifiers = []
    def generic_visit(self, node):
        ast.NodeVisitor.generic_visit(self, node)
    def visit_Name(self, node):
        # You can specify othe exceptions here than cos or sin
        if node.id not in ['cos', 'sin']:
            self.identifiers.append(node.id)

然后定义一个快速函数,该函数接受一个表达式来给出它的标识符:

>>> 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']

ast模块使用python 2.6或2.7。