使用RPN形式的函数

usage of functions with RPN form

本文关键字:函数 RPN 使用      更新时间:2023-10-16

我试图将数学表达式转换为RPN,然后对它们进行符号微分,但我被一些函数卡住了,如sin() cos() tan()…Ln()√()等等。我的表达式解析器只适用于更简单的情况,比如来自RPN wiki的一个:

3+4*2/(1-5)^2^3

产生如下结果:

342*15-23^^/+

然而,当涉及到更复杂的公式时,例如:

sin(2*x^2+6)-(cos(x)/(1-x))

我也不能真正手工创建RPN。我目前工作的极简解是根据分流场算法Wiki上定义的算法再次实现的。

std::string ParseExpression(const std::string &expr) {
    std::string ops = "-+/*^";
    std::stringstream output;
    std::stack<int> stack;
    typedef std::string::const_iterator StringIterator;
    for (StringIterator TOKEN = expr.cbegin(), END = expr.cend(); TOKEN != END; ++TOKEN) {
        const char c = *TOKEN;
        size_t idx = ops.find(c);
        if (idx != std::string::npos) {
            if (stack.empty()) {
                stack.push(idx);
            }
            else {
                while (!stack.empty()) {
                    int prec2 = stack.top() / 2;
                    int prec1 = idx / 2;
                    if (prec2 > prec1 || (prec2 == prec1 && c != '^')) {
                        output << ops[stack.top()];
                        stack.pop();
                    }
                    else {
                        break;
                    }
                }
                stack.push(idx);
            }
        } else if (c == '(') {
            stack.push(-2);
        } else if (c == ')') {
            while (stack.top() != -2) {
                char op = stack.top();
                stack.pop();
                output << ops[op];
            }
            stack.pop();
        } else {
            output << c;
        }
    }
    while (!stack.empty()) {
        output << ops[stack.top()];
        stack.pop();
    }
    return output.str();
}

如何在RPN公式中实际包含三角函数和其他函数并正确处理它们?

RPN对函数(包括三角函数)的作用与对运算符的作用相同。对于三角函数,只有一个参数(不像运算符,通常有两个)。

你的例子
sin(2*x^2+6)-(cos(x)/(1-x))

会变成类似

的东西
2x2^*6+_sin_x_cos_1x-/-

为了清晰起见,我在sin和cos函数周围加上了前后下划线。

更抽象一点,如果你把运算符看作是双参数函数,而三角函数看作是单参数函数,这可能更有意义——函数总是出现在它的参数之后,并按照堆栈弹出的顺序(后进先出)计算前面的参数。将操作符更改为函数(并为二进制添加"b",为一元添加"u")将得到下面的内容。RPN表示,对于任何带有"b"(两个参数)的东西,前两个参数将在函数中求值。对于以"u"结尾的函数(只有一个参数),计算前一个参数。

2x2_powb__multb_6_plusb__sinu_x_cosu_1x_minusb__divb__minusb_