我试图将数学表达式转换为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公式中实际包含三角函数和其他函数并正确处理它们?
答案 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_