软件编程
位置:首页>> 软件编程>> java编程>> java代码执行字符串中的逻辑运算方法

java代码执行字符串中的逻辑运算方法

作者:Zzooper  发布时间:2023-11-29 12:13:06 

标签:java,字符串,运算

方式一


public class Test
{
public static void main(String[] args) throws Exception {
  String str = "(a or b) and c";
  str = str.replaceAll("or", "||");
  str = str.replaceAll("and", "&&");
  System.out.println(str);
  ScriptEngineManager manager = new ScriptEngineManager();
  ScriptEngine engine = manager.getEngineByName("js");
  engine.put("a",true);
  engine.put("b",false);
  engine.put("c",true);  
  Object result = engine.eval_r(str);
  System.out.println("结果类型:" + result.getClass().getName() + ",计算结果:" + result);
 }
}

这种方式使用js的方式进行运算,使用较简单,但是当运算double类型的四则运算时结果会出现循环小数,运算结果会出现问题.

方式二(能够保证四则运算精度):


/**
* @Project:  BizRule  
* @File:   org.coffeesweet.util.MathExpress.java
* @Author:  coffeesweet
* @Date:   2011-3-28
* @Description: 2011 coffeesweet Inc. All rights reserved.
*/
package org.coffeesweet.util;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author coffeesweet
* +,-,*,/四则运算的表达式逆波兰解析计算类,精确计算,应用BigDecimal类处理
* 支持负数,但规范除整个表达式第一个数为负数时可以不出现在'('后,其它表达式中间任何位置的
* 负数必须出现在'('后,即:用括号括起来。比如:-3+(-2+1)*10或-3+((-2)+1)*10或(-3)+(-2+1)*10或(-3)+((-2)+1)*10
*/
public class MathExpress {
/**
 * +
 */
private final static String OP1 = "+";
/**
 * -
 */
private final static String OP2 = "-";
/**
 * *
 */
private final static String OP3 = "*";
/**
 * /
 */
private final static String OP4 = "/";
/**
 * ^
 */
// private final static String OP5 = "^";
/**
 * %
 */
// private final static String OP6 = "%";
/**
 * (
 */
private final static String OPSTART = "(";
/**
 * )
 */
private final static String OPEND = ")";
/**
 * !用来替代负数前面的'-'
 */
// private final static String NEGATIVESING = "!";
/**
 * !用来替代负数前面的'+'
 */
// private final static String PLUSSING = "@";
/**
 * '#'用来代表运算级别最低的特殊字符
 */
// private final static String LOWESTSING = "#";
//最原始的四则运算式
private String expBase;
//经过初始化处理后的四则运算式
private String expInited;
//精度
private int precision=10;
//取舍模式
private RoundingMode roundingMode=RoundingMode.HALF_UP;
//精度上下文
private MathContext mc;
//四则运算解析
private List<String> expList = new ArrayList<String>();
//存放逆波兰表达式
private List<String> rpnList = new ArrayList<String>();
public MathExpress(){
}
public MathExpress(String expBase) {
 init(expBase,this.precision,this.roundingMode);
}
public MathExpress(String expBase,int precision,RoundingMode roundingMode){
 init(expBase,precision,roundingMode);
}
public void init(String expBase,int precision,RoundingMode roundingMode){
 this.expBase = expBase;
 this.precision = precision;
 this.roundingMode = roundingMode;
 this.mc = new MathContext(precision,roundingMode);
 this.expInited = initExpress(expBase);
 StringTokenizer st = new StringTokenizer(this.expInited,"+-*/^%()",true);
 while(st.hasMoreElements()){
  this.expList.add(st.nextElement().toString().trim());
 }
 this.rpnList = initRPN(this.expList);
}
/**
 * @return the expBase
 */
public String getExpBase() {
 return expBase;
}
/**
 * @param expBase the expBase to set
 */
public void setExpBase(String expBase) {
 this.expBase = expBase;
}
/**
 * @return the expInited
 */
public String getExpInited() {
 return expInited;
}
/**
 * @param expInited the expInited to set
 */
public void setExpInited(String expInited) {
 this.expInited = expInited;
}
/**
 * @return the precision
 */
public int getPrecision() {
 return precision;
}
/**
 * @param precision the precision to set
 */
public void setPrecision(int precision) {
 this.precision = precision;
}
/**
 * @return the roundingMode
 */
public RoundingMode getRoundingMode() {
 return roundingMode;
}
/**
 * @param roundingMode the roundingMode to set
 */
public void setRoundingMode(RoundingMode roundingMode) {
 this.roundingMode = roundingMode;
}
/**
 * @return the expList
 */
public List<String> getExpList() {
 return expList;
}
/**
 * @param expList the expList to set
 */
public void setExpList(List<String> expList) {
 this.expList = expList;
}
/**
 * @return the rpnList
 */
public List<String> getRpnList() {
 return rpnList;
}
/**
 * @param rpnList the rpnList to set
 */
public void setRpnList(List<String> rpnList) {
 this.rpnList = rpnList;
}
/**
 * @return the mc
 */
public MathContext getMc() {
 return mc;
}
/**
 * @param mc the mc to set
 */
public void setMc(MathContext mc) {
 this.mc = mc;
}
/**
 * 去除空白字符和在负号'-'前加'0',便于后面的StringTokenizer
 * @param exp
 * @return
 */
private static String initExpress(String exp){
 String reStr = null;
 reStr = exp.replaceAll("\\s", "");
 if(reStr.startsWith("-")){
  reStr = "0"+reStr;
 }
 reStr = reStr.replaceAll("\\(\\-", "(0-");
 return reStr;
}
/**
 * 是否是整数或是浮点数,但默认-05.15这种也认为是正确的格式
 * @param str
 * @return
 */
private boolean isNumber(String str){
 Pattern p = Pattern.compile("^(-?\\d+)(\\.\\d+)?$");
 Matcher m = p.matcher(str);
 boolean isNumber = m.matches();
 return isNumber;
}
/**
 * 设置优先级顺序()设置与否无所谓
 * @param sign
 * @return
 */
private int precedence(String str){
 char sign = str.charAt(0);
 switch(sign){
  case '+':
  case '-':
   return 1;
  case '*':
  case '/':
   return 2;
  case '^':
  case '%':
   return 3;
  case '(':
  case ')':
//   case '#':
  default:
   return 0;
 }
}
/**
 * 转变为逆波兰表达式
 * @param strList
 * @return
 */
public List<String> initRPN(List<String> strList){
 List<String> returnList = new ArrayList<String>();
 //用来存放操作符的栈
 Stack stack = new Stack();
//  stack.push(LOWESTSING);
 int length = strList.size();
 for(int i=0;i<length;i++ ){
  String str = strList.get(i);
  if(isNumber(str)){
   returnList.add(str);
  }else{
   if(str.equals(OPSTART)){
    //'('直接入栈
    stack.push(str);
   }else if(str.equals(OPEND)){
    //')'
    //进行出栈操作,直到栈为空或者遇到第一个左括号
    while (!stack.isEmpty()) {
     //将栈顶字符串做出栈操作
     String tempC = stack.pop();
     if (!tempC.equals(OPSTART)) {
      //如果不是左括号,则将字符串直接放到逆波兰链表的最后
      returnList.add(tempC);
     }else{
      //如果是左括号,退出循环操作
      break;
     }
    }
   }else{
    if (stack.isEmpty()) {
     //如果栈内为空
     //将当前字符串直接压栈
     stack.push(str);
    }else{
     //栈不空,比较运算符优先级顺序
     if(precedence(stack.top())>=precedence(str)){
      //如果栈顶元素优先级大于当前元素优先级则
      while(!stack.isEmpty() && precedence(stack.top())>=precedence(str)){
       returnList.add(stack.pop());
      }
     }
     stack.push(str);
    }
   }
  }
 }
 //如果栈不为空,则将栈中所有元素出栈放到逆波兰链表的最后
 while (!stack.isEmpty()) {
  returnList.add(stack.pop());
 }
 return returnList;
}
/**
 * 计算逆波兰表达式
 * @param rpnList
 * @return
 */
public String caculate(List<String> rpnList){
 Stack numberStack = new Stack();
 int length=rpnList.size();
 for(int i=0;i<length;i++){
  String temp=rpnList.get(i);
  if(isNumber(temp)){
   numberStack.push(temp);
  }else{
   BigDecimal tempNumber1 = new BigDecimal(numberStack.pop(),this.mc);
   BigDecimal tempNumber2 = new BigDecimal(numberStack.pop(),this.mc);
   BigDecimal tempNumber = new BigDecimal("0",this.mc);
   if(temp.equals(OP1)){
    tempNumber=tempNumber2.add(tempNumber1);
   }else if(temp.equals(OP2)){
    tempNumber=tempNumber2.subtract(tempNumber1);
   }else if(temp.equals(OP3)){
    tempNumber=tempNumber2.multiply(tempNumber1);
   }else if(temp.equals(OP4)){
    tempNumber=tempNumber2.divide(tempNumber1,
      precision,
      roundingMode);
   }
   numberStack.push(tempNumber.toString());
  }
 }
 return numberStack.pop();
}
/**
 * 按照类的缺省参数进行计算
 * @return
 */
public String caculate(){
 return caculate(this.rpnList);
}
/**
 * 数字条件表达式精确比较
 * eg: "3.0>2" "1<5" "1==5" "1!=5" "(1.0+2)>3" "((-0.9+3)>=2. 1)"
 * 不支持&&,||等连接符
 * @param str
 * @return
 */
public static boolean compareTo(String strParm){
 boolean reBoolean = false;
 boolean isParentheses = false;//标记是否有()括上整个字符串
 String str = initExpress(strParm);
 Pattern p = Pattern.compile("^\\([\\s\\S]*\\)$");
 Matcher m = p.matcher(str);
 isParentheses = m.matches();
 if(-1==str.indexOf(">=")&&-1==str.indexOf("<=")&&-1==str.indexOf("==")&&-1==str.indexOf("!=")){
  if(-1==str.indexOf(">")&&-1==str.indexOf("<"))
  throw new IllegalArgumentException("异常:条件表达式不正确!");
 }
 if(-1 != str.indexOf(">=")){
  String[] strTemps = str.split(">=");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( -1 == r ){
   reBoolean = false;
  }else{
   reBoolean = true;
  }
 }else if(-1 != str.indexOf("<=")){
  String[] strTemps = str.split("<=");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( 1 == r ){
   reBoolean = false;
  }else{
   reBoolean = true;
  }
 }else if(-1 != str.indexOf("==")){
  String[] strTemps = str.split("==");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( 0 == r ){
   reBoolean = true;
  }else{
   reBoolean = false;
  }
 }else if(-1 != str.indexOf("!=")){
  String[] strTemps = str.split("!=");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( 0 != r ){
   reBoolean = true;
  }else{
   reBoolean = false;
  }
 }else if((-1 != str.indexOf(">")) && (-1 == str.indexOf("="))){
  String[] strTemps = str.split(">");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( 1 == r ){
   reBoolean = true;
  }else{
   reBoolean = false;
  }
 }else if((-1 != str.indexOf("<")) && (-1 == str.indexOf("="))){
  String[] strTemps = str.split("<");
  if(isParentheses){
   strTemps[0] = strTemps[0] + ")";
   strTemps[1] = "(" + strTemps[1];
  }
  int r = new BigDecimal((new MathExpress(strTemps[0]).caculate())).compareTo(new BigDecimal((new MathExpress(strTemps[1]).caculate())));
  if( -1 == r ){
   reBoolean = true;
  }else{
   reBoolean = false;
  }
 }
 return reBoolean;
}
public static void main(String...args){
//  MathExpress me = new MathExpress("-(-0.5+0.1)*10+2",10,RoundingMode.HALF_UP);
//  System.out.println(me.getExpList());
//  List<String> tempList = me.initRPN(me.getExpList());
//  System.out.println(tempList);
//  String resultStr = me.caculate(tempList);
//  System.out.println(resultStr);
 MathExpress me = new MathExpress("-(-1.5000000003+0.1)*10+2");
 String resultStr = me.caculate();
 BigDecimal bd = new BigDecimal(resultStr);
 BigDecimal bd2 = bd.setScale(2, RoundingMode.HALF_UP);
 System.out.println(me.caculate());
 System.out.println(bd.toString());
 System.out.println(bd.scale());
 System.out.println(bd2.toString());
 System.out.println(bd2.scale());
//  System.out.println("------------------------------------");
//  Pattern p = Pattern.compile("^\\([\\s\\S]*\\)$");//匹配类似以'('开头')'结尾的字符串
//  Matcher m = p.matcher("(2. 0>2.22)");
//  System.out.println(m.matches());
 boolean reBoolean = MathExpress.compareTo("((-8.0+3)>=2. 1)");
 System.out.println(reBoolean);
}
/**
 * 栈
 */
private class Stack {
 LinkedList<String> stackList = new LinkedList<String>();
 public Stack() {
 }
 /**
  * 入栈
  * @param expression
  */
 public void push(String expression) {
  stackList.addLast(expression);
 }
 /**
  * 出栈
  * @return
  */
 public String pop() {
  return stackList.removeLast();
 }
 /**
  * 栈顶元素
  * @return
  */
 public String top() {
  return stackList.getLast();
 }
 /**
  * 栈是否为空
  * @return
  */
 public boolean isEmpty() {
  return stackList.isEmpty();
 }
}
}

来源:https://blog.csdn.net/qq_27739989/article/details/72551029

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com