数学表达式解析
本文最后更新于:2026年3月30日 凌晨
数学表达式解析
最近碰到一个需求,要把字符串形式的表达式解析出来,交给前端或者后端去计算。比如这种:
1 | |
核心要求不算复杂,主要是这几条:
- 支持基本的加减乘除和括号。
- 支持变量。
- 支持自定义函数。
- 最好前后端都能找到比较顺手的实现方式。
我分别看了 Java、Python 和 JavaScript 的方案,这里做个记录。
Java
1. exp4j
官网:
https://www.objecthunter.net/exp4j/#Custom_functions
参考链接:
https://ibit.tech/archives/exp4j-introduction
exp4j 对基础数学表达式的支持挺完整,接入也比较轻,语法直观,算是上手成本最低的一类方案。
它的问题主要出在自定义函数上。Function 必须提前声明参数个数,所以像 sum(1, 2, 3, 4) 这种可变参数函数,实现起来就不太舒服。
如果你的函数基本都是固定参数,比如 max(a, b)、round(x) 这种,那 exp4j 其实已经够用了。
1 | |
2. JEP
官网:
https://www.singularsys.com/jep/doc/html/usage.html#gettingstarted
JEP 的能力会更完整一些,但我看了下文档和示例,整体用法对这次需求来说有点重,语法也不是我特别喜欢的风格,所以没有继续往下试。
3. ibit-exp4j
地址:
https://github.com/ibit-tech/ibit-exp4j
它是在 exp4j 基础上又封装了一层,但我实际看下来,并没有比直接使用 exp4j 更顺手,反而多了一层理解成本。
Java 小结
如果是 Java 场景,而且表达式能力不算特别复杂,我最后还是会优先选 exp4j。它不完美,但足够轻,也足够直接;真正的短板主要在“可变参数自定义函数”这里。
Python
Python 这边最直接的办法其实就是 eval。
它最大的优点是省事:几乎不用额外引库,表达式、变量、自定义函数都能直接跑起来。
1 | |
global_vars 和 local_vars 分别用来控制可用的函数和变量。如果不传,默认会落到当前全局作用域。
但 eval 最大的问题也很明显:它太灵活了,所以安全性会差一些。
如果表达式内容来自用户输入,或者来自不可信配置,直接使用 eval 风险非常大。这种方式更适合:
- 内部系统。
- 表达式来源完全可控的场景。
- 临时脚本或者原型验证。
如果要做成正式产品能力,最好还是加一层白名单和语法限制,或者直接换成更安全的表达式解析方案。
JavaScript
JavaScript 这边我最后看到的是 math.js,整体体验是三种语言里最顺手的。
官网:
https://mathjs.org/docs/expressions/parsing.html
它不只是支持普通数学表达式,还支持变量、函数、单位换算,parser 的状态管理也比较方便。
1 | |
如果前端要做表达式输入、预计算、公式编辑器这类功能,math.js 的可用性确实很高,能省掉不少自己造轮子的工作。
最后怎么选
如果只基于这次需求,我的结论大概是这样:
- Java:选
exp4j,适合基础数学表达式和固定参数自定义函数。 - Python:
eval最省事,但一定要限定在可信输入场景。 - JavaScript:
math.js最完整,前端场景基本可以直接用。
如果是要做一套“允许用户自由输入公式”的通用能力,我会更偏向下面这种组合:
- 前端用
math.js。 - 后端不要直接用
eval。 - Java 侧如果表达式规则相对固定,就用
exp4j。
补一句
这类需求真正难的,往往不是“算出来”,而是“让用户能安全、稳定、可控地算出来”。
语法支持只是第一步,后面通常还会碰到这些问题:
- 函数白名单怎么限制。
- 变量怎么注入。
- 非法表达式怎么报错。
- 精度怎么处理。
所以表达式解析这玩意,看起来像是个小功能,做起来其实也挺不容易哦。