You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将含√、Σ等符号函数的无括号表达式转换为RPN形式

问题背景

我目前在实现符号化函数(使用√、Σ这类专用符号表示的函数)到RPN(逆波兰表达式)的转换逻辑,现有实现存在转换错误:

  • 测试表达式√√100会被错误转换为√100√
  • 预期正确转换结果为100√√
    虽然可以通过显式加括号写成√(√(100))的形式得到正确结果,但这种写法会让复杂表达式变得非常冗余,因此需要在不额外添加括号的前提下实现正确转换。
现有实现代码
std::wstring revpol(std::wstring parsedf, std::wstring mtok)
{
    std::wstring tparsed;
    std::wistringstream mplit(parsedf);
    while(mplit >> mtok)
    {
        mspec = false;
        if(rxm(mtok,pnum))
        {
            tparsed += mtok + L" ";
        }
        else{
            if(Pval[mtok] == 0)
            {
                mspec = true;
            }
            if(mspec){
                if(mtok == L"(")
                {
                    preop.push({mtok,Pval[mtok]});
                    mspec = false;
                }
                else if(mtok == L")") {
                    while(preop.top().first != L"(")
                    {
                        tparsed += preop.top().first + L" ";
                        preop.pop();
                    }
                    if(preop.top().first == L"(")
                    {
                        preop.pop();
                    }
                    mspec = false;
                }
                else if(mtok == L",")
                {
                    tparsed += mtok + L" ";
                    mspec = false;
                }
                else{
                    if(mtok.back() == '$'){
                        // to be changed
                        Tmtok = mtok;
                        mtok.pop_back();
                        Pval.insert({mtok,3});
                        mtok = Tmtok;
                        mspec = false;
                        std::cout<<preop.size()<<std::endl;
                        while(!preop.empty() && preop.top().second >= 3 && mtok != L"^")
                        {
                            tparsed += preop.top().first + L" ";
                            preop.pop();
                        }
                        preop.push({mtok,3});
                    }
                    else{
                        tparsed += mtok + L" ";
                        mspec = false;
                    }
                }
            }
        }
    }
    // 原代码未贴出遍历完成后清空运算符栈的逻辑
}
错误原因

当前实现基于调度场算法,但没有正确处理一元前缀运算符的逻辑:

  • 没有对一元前缀运算符(如√)做单独的属性标记,和二元运算符混用了优先级、结合性规则
  • 运算符出栈判断逻辑错误:对于右结合的运算符(包括前缀一元运算符、幂运算符^),不应该在栈顶优先级大于等于当前优先级时出栈,仅当栈顶优先级大于当前优先级时才需要出栈
  • 对于不带$标记的运算符,现有逻辑直接将其输出到结果串,完全跳过了运算符栈的调度流程,是导致√√100转换错误的核心原因之一
修复方法
  1. 单独定义一元前缀运算符的属性:给√这类一元前缀运算符设置高于所有二元运算符的优先级(比如设为4),明确标记为右结合
  2. 移除“非标记运算符直接输出到结果”的分支,所有运算符都必须进入运算符栈走统一的调度逻辑
  3. 调整入栈前的弹出规则:
    • 遇到左结合运算符,循环弹出栈中优先级大于等于当前运算符的元素到结果串
    • 遇到右结合运算符(含一元前缀运算符、^),循环弹出栈中优先级严格大于当前运算符的元素到结果串
  4. 表达式遍历完成后,把运算符栈中剩余的所有元素依次弹出到结果串

修复后√√100的处理流程为:

  1. 读入第一个√,栈空直接压入运算符栈
  2. 读入第二个√,栈顶为同优先级右结合运算符,不弹出,直接压栈
  3. 读入数字100,直接追加到结果串,当前结果为100
  4. 表达式遍历完成,依次弹出栈内的两个√追加到结果,最终得到100√√,符合预期。

内容的提问来源于stack exchange,提问作者bigbroin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 06:03:12