java 实现公式或算法校验及计算
//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; } }