前言
最近遇到一个客户在流程表单明细中要计算纳税税额、税前或税后所得额的计算。
例如:选择 特许权使用费所得,根据税前,税前金额,需要计算出税额和税后所得额。
想了想java传统运算各种情况太麻烦,研究了一下jexl3。
maven依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-jexl3</artifactId>
<version>3.1</version>
</dependency>
核心方法
看了一些网上的方法,都没有考虑精度的问题,于是结合了一下,把精度计算加进去。
/**
* 公式计算
*
* @param expression 公式的表达式
* @param map 传入参数和值
* @param margin 保留小数位数
* @return
*/
public static BigDecimal convertToCode(String expression, Map<String, Object> map, int margin) {
JexlEngine jexl = new Engine();
JexlContext jexlContext = new MapContext();
//需要set源代码Math,否则报错
jexlContext.set("Math", Math.class);
//需要set源代码 BigDecimal,否则报错
jexlContext.set("BigDecimal", BigDecimal.class);
for (String key : map.keySet()) {
Object p = map.get(key);
Double val = 0.0;
if (null != p) {
if (p instanceof BigDecimal) {
BigDecimal temp = (BigDecimal) p;
val = temp.doubleValue();
} else {
if (NumberUtil.isNumber(p.toString())) {
val = Double.valueOf(p.toString());
}
}
}
jexlContext.set(key, val);
}
JexlExpression e = jexl.createExpression(expression);
Object obj = e.evaluate(jexlContext);
BigDecimal result = new BigDecimal(null == obj ? "0" : obj.toString());
return result.setScale(margin, BigDecimal.ROUND_HALF_UP);
}
//因为精度问题引入BigDecimal
public static void main(String[] args) {
Map<String, Object> map = new HashMap<String, Object>();
double A = 100;
map.put("A", A);
//税后所得额计算公式
String shsde_formula = "0.8*A+160";
BigDecimal bigDecimal = convertToCode(shsde_formula, map, 5);
System.out.println("bigDecimal = " + bigDecimal);
}
测试结果:
小结
希望对大家有所帮助!