Java中不使用jeval如何从表达式字符串计算获取精确数值?
高精度表达式计算解决方案
问题根因
你遇到的精度问题是因为jeval底层默认使用double类型做运算,浮点数本身的存储特性导致0.1+0.2这类计算出现误差,你自己用BigDecimal硬编码运算可以解决问题,但没法适配动态表达式的场景。
现成工具库推荐
直接用成熟的表达式引擎即可,不需要自己手写全链路解析逻辑,目前主流支持BigDecimal高精度运算的工具如下:
AviatorScript(推荐)
阿里开源的高性能表达式引擎,原生支持一键开启高精度模式,自动处理所有运算的精度问题。
Maven依赖配置:
<dependency> <groupId>com.googlecode.aviator</groupId> <artifactId>aviator</artifactId> <version>5.4.1</version> </dependency>
通用计算函数封装示例:
import com.googlecode.aviator.AviatorEvaluator; import com.googlecode.aviator.Options; import java.math.MathContext; import java.math.RoundingMode; public class HighPrecisionCalc { // 初始化配置,全局只需要执行一次 static { // 所有浮点数自动解析为BigDecimal,避免浮点精度丢失 AviatorEvaluator.setOption(Options.ALWAYS_PARSE_FLOATING_POINT_NUMBER_INTO_BIGDECIMAL, true); // 配置全局运算规则:精度保留16位,四舍五入,可按需调整 AviatorEvaluator.setOption(Options.MATH_CONTEXT, new MathContext(16, RoundingMode.HALF_UP)); } public static String calculate(String expression) { return AviatorEvaluator.execute(expression).toString(); } public static void main(String[] args) { // 测试场景1 System.out.println(calculate("(0.1+0.2)")); // 输出 0.3 // 测试场景2 System.out.println(calculate("(0.1+0.2)*10+15/3")); // 输出 8 } }
Apache Commons JEXL3
如果项目已经依赖commons系列组件,也可以选择JEXL3,通过配置算术解析器即可实现BigDecimal高精度运算,适配复杂表达式场景。
自定义实现思路(无第三方依赖场景)
如果不想引入额外jar包,可以自己实现通用解析逻辑,步骤如下:
- 词法分析:拆分表达式为数字、运算符、括号三类token
- 中缀转后缀:将常规写法的中缀表达式转为逆波兰表达式,处理运算符优先级、括号嵌套逻辑
- 栈运算:遍历后缀表达式,数字直接转BigDecimal压栈,遇到运算符则弹出栈顶两个元素执行对应的BigDecimal运算,结果重新压栈
- 结果输出:栈内最后剩余的元素就是最终计算结果
注意:自定义实现时必须指定除法的舍入模式,否则遇到除不尽的场景会直接抛出算术异常;所有数字必须用字符串构造BigDecimal,不能从double类型转换,否则构造阶段就会出现精度丢失。
内容的提问来源于stack exchange,提问作者flower
相关产品推荐
相关产品推荐

