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

如何高效存储含变量的数学表达式以实现快速多次求值?

高效存储解析后数学表达式以支持多组变量求值的方案

你选择用逆波兰表示法(RPN)的令牌数组存储解析结果的思路完全正确——这种结构天生适合栈式求值,且表达式结构固定,仅需更新变量值就能重复计算,完美匹配你多组变量求值的需求。

针对你纠结的运算符和函数存储问题,函数指针是最优方案之一,兼具速度和内存效率,下面给出具体的优化方案:

优化后的Token结构设计

将运算符拆分为一元/二元类型(求值时栈操作逻辑不同),直接在Token的union中存储函数指针,避免额外的参数结构体开销:

// 定义函数指针类型,统一返回double适配浮点求值
typedef double (*BinaryOp)(double, double);   // 二元运算符:+、-、*、/、^等
typedef double (*UnaryOp)(double);            // 一元运算符:负号、平方根等
typedef double (*MathFunc)(double);           // 数学函数:sin、cos、log等

enum TokenType {
    NUMBER,      // 常量数值
    VARIABLE,    // 变量
    BINARY_OP,   // 二元运算符
    UNARY_OP,    // 一元运算符
    FUNCTION     // 数学函数
};

struct Token {
    TokenType type;
    union {
        double value;               // NUMBER类型:存储常量值(建议用double支持浮点)
        int variable_index;         // VARIABLE类型:变量在值数组中的索引
        BinaryOp binary_op;         // BINARY_OP类型:指向二元运算函数的指针
        UnaryOp unary_op;           // UNARY_OP类型:指向一元运算函数的指针
        MathFunc math_func;         // FUNCTION类型:指向数学函数的指针
    };
};

结构优势:

  • 内存紧凑:union共享内存空间,每个Token仅占sizeof(TokenType) + sizeof(最大成员)(64位系统下约16字节)
  • 求值直接:无需查表或字符串匹配,直接调用函数指针完成计算,速度最快

求值流程(多次复用)

  1. 维护一个double类型的求值栈,以及一个存储变量值的数组(比如double vars[],索引对应Token的variable_index)
  2. 遍历RPN令牌数组,按类型处理:
    • NUMBER:将value压入栈
    • VARIABLE:根据variable_index从变量数组取值,压入栈
    • UNARY_OP:弹出栈顶元素,调用unary_op计算,结果压回栈
    • BINARY_OP:弹出两个元素(注意顺序:先弹的是右操作数),调用binary_op计算,结果压回栈
    • FUNCTION:弹出对应参数个数的元素(如sin弹1个),调用math_func计算,结果压回栈
  3. 遍历结束后,栈顶元素即为当前变量组对应的表达式结果

额外优化建议

  • 变量数组用连续内存(如C++的std::vector<double>或C的动态数组),保证快速随机访问
  • 对于频繁使用的表达式,可以预分配求值栈的内存,避免每次求值时的内存分配开销
  • 如果表达式中有重复常量,可共享同一个Token实例,进一步减少内存占用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:50:09