使用RPN表单的函数

时间:2014-06-18 07:03:38

标签: c++ postfix-notation

我试图将数学表达式转换为RPN,然后对它们执行符号区分,但我仍然坚持使用像sin()cos()tan()... ln()sqrt这样的函数(我的表达式解析器仅适用于更简单的情况,例如来自RPN wiki:

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

产生以下内容:

342*15-23^^/+

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

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

我无法手动创建RPN。我目前工作的极简主义解决方案再次根据Shunting-Yard算法的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公式中实际包含三角函数和其他函数并正确处理它们?

1 个答案:

答案 0 :(得分:1)

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

你的例子

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

会变成类似

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

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

更抽象地说,如果你认为运算符是双参数函数而三角函数作为单参数函数,它可能会更有意义 - 函数总是在它的参数之后并且在堆栈中评估前面的args-弹出顺序(后进先出)。将操作符更改为函数(并附加&#34; b&#34;用于二进制文件,&#34; u&#34;用于一元)将为我们提供以下内容。 RPN说,对于任何有&#34; b&#34; (两个参数),在函数中计算前两个args。对于以&#34; u&#34;结尾的函数(一个参数),前面的参数被评估。

2x2_powb__multb_6_plusb__sinu_x_cosu_1x_minusb__divb__minusb_