//1.引入jar
<!--自定义公式计算类库-->
<dependency>
<groupId>com.scireum</groupId>
<artifactId>parsii</artifactId>
<version>1.5</version>
</dependency>
//2.源码如下
package com.liansheng.swap.utils;
import com.liansheng.swap.appStart.netty.server.RedisConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import parsii.eval.Expression;
import parsii.eval.Parser;
import parsii.eval.Scope;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**公式计算器**/
@Component
public class EquationCalculator {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private RedisUtils redisUtils;
/**
* 公式计算
* @param formula
* @return
* @throws Exception
*/
public double formulaCalculation(String formula) throws Exception {
// Long start = System.currentTimeMillis();
//去除空格
formula = formula.replaceAll(" ","");
/** 获取变量表 **/
List<String> varList = getVarList(formula);
/** 进行计算 **/
double result = calcByParsii(formula,varList);
// System.out.println("自定义公式计算总耗时:"+(System.currentTimeMillis()-start) + " 运算结果:"+result);
return result;
}
/**
* 获取变量表
*
* @param formula
**/
public static List<String> getVarList(String formula) {
List<String> varList = new ArrayList<>();
String str = formula;
while (str.contains("STARTFLAG")&&str.contains("ENDFLAG")){
int start = str.indexOf("STARTFLAG");
int end = str.indexOf("ENDFLAG")+7;
if(start<end){
String ponitPara = str.substring(start,end);
/*
if(!varList.contains(ponitPara)){
varList.add(ponitPara);
}
*/
varList.add(ponitPara);
str = str.substring(end);
}
}
return varList;
}
/**
* 公式计算
* @param exp
* @return
*
* 替代方法:calcProc
*/
private double calcByParsii (String exp,List<String> varList) throws Exception {
//exp = "2 + (7-5) * 3.14159 * x + sin(0)";
//exp = "((1+2)*2+(3-2)*3)+((1+2)/3+(2+4)/3)*2";
// compile
Scope scope = Scope.create();
Expression parsiiExpr = Parser.parse(exp,scope);
for (String key : varList) {
Map pointInfo = redisUtils.hmget(RedisConfig.KEY_MONITOR + key.replaceAll("STARTFLAG","").replaceAll("ENDFLAG","").replaceAll("DELIMITER",":"));
if(pointInfo!=null&&pointInfo.size()>1){
Double value = Double.parseDouble(pointInfo.get("value").toString());
scope.getVariable(key).setValue(value);
}else {
throw new RuntimeException("自定义公式:"+exp+"运算时,未获取到配置测点:"+key+"的数据");
}
}
// evaluate
double result = parsiiExpr.evaluate();
return result;
}
/**
* 公式校验
*/
public double formulaCheck(String formula) throws Exception {
formula = formula.replaceAll(" ","");
if(formula.contains("ENDFLAGSTARTFLAG")){
throw new RuntimeException("变量之间运算符!");
}
List<String> varList = getVarList(formula);
double result = calcByParsiiForCheck(formula,varList);
return result;
}
/**
* 公式验证
*/
private double calcByParsiiForCheck (String exp,List<String> varList) throws Exception {
Scope scope = Scope.create();
Expression parsiiExpr = Parser.parse(exp,scope);
for (String key : varList) {
scope.getVariable(key).setValue(1);
}
double result = parsiiExpr.evaluate();
return result;
}
}