java中解析计算公式

数据类型为BigDecimal,涉及到金额计算最好用BigDecimal.

package com.nantian.iwap.app.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 公式运算
 * */
public class SZYSUtils {

	private static BigDecimal BigDecimalCal(BigDecimal a1, BigDecimal a2, char operator) throws Exception {
        switch (operator) {
        case '+':
        	return a1.add(a2);
            //return a1 + a2;
        case '-':
        	return a1.subtract(a2);
            //return a1 - a2;
        case '*':
        	return a1.multiply(a2);
            //return a1 * a2;
        case '/':
        	return a1.divide(a2,20,BigDecimal.ROUND_HALF_UP);
            //return a1 / a2;
        default:
            break;
        }
        throw new Exception("illegal operator!");
    }

	private static int getPriority(String s) throws Exception {
        if(s==null) return 0;
        else if(s.equals("(")) return 1;
        else if(s.equals("+") || s.equals("-")) return 2;
        else if(s.equals("*") || s.equals("/")) return 3;
        
        /*
        switch(s) {
        case "(":return 1;
        case "+":;
        case "-":return 2;
        case "*":;
        case "/":return 3;
        default:break;
        }
        */
        
        throw new Exception("illegal operator!");
    }

	public static String getResult(String expr) throws Exception {
       // System.out.println("计算"+expr);
        /*数字栈*/
        Stack<BigDecimal> number = new Stack<BigDecimal>(); 
        /*符号栈*/
        Stack<String> operator = new Stack<String>();
        operator.push(null);// 在栈顶压人一个null,配合它的优先级,目的是减少下面程序的判断

        /* 将expr打散为运算数和运算符 */
        Pattern p = Pattern.compile("(?<!\\d)-?\\d+(\\.\\d+)?|[+\\-*/()]");// 这个正则为匹配表达式中的数字或运算符
        Matcher m = p.matcher(expr);
        while(m.find()) {
            String temp = m.group();
            if(temp.matches("[+\\-*/()]")) {//遇到符号
                if(temp.equals("(")) {//遇到左括号,直接入符号栈
                    operator.push(temp);
                    //System.out.println("符号栈更新:"+operator);
                }else if(temp.equals(")")){//遇到右括号,"符号栈弹栈取栈顶符号b,数字栈弹栈取栈顶数字a1,数字栈弹栈取栈顶数字a2,计算a2 b a1 ,将结果压入数字栈",重复引号步骤至取栈顶为左括号,将左括号弹出
                    String b = null;
                    while(!(b = operator.pop()).equals("(")) {
                       // System.out.println("符号栈更新:"+operator);
                        BigDecimal a1 = number.pop();
                        BigDecimal a2 = number.pop();
                       // System.out.println("数字栈更新:"+number);
                       // System.out.println("计算"+a2+b+a1);
                        number.push(BigDecimalCal(a2, a1, b.charAt(0)));
                       // System.out.println("数字栈更新:"+number);
                    }
                    //System.out.println("符号栈更新:"+operator);
                }else {//遇到运算符,满足该运算符的优先级大于栈顶元素的优先级压栈;否则计算后压栈
                    while(getPriority(temp) <= getPriority(operator.peek())) {
                        BigDecimal a1 = number.pop();
                        BigDecimal a2 = number.pop();
                        String b = operator.pop();
//                        System.out.println("符号栈更新:"+operator);
//                        System.out.println("数字栈更新:"+number);
//                        System.out.println("计算"+a2+b+a1);
                        number.push(BigDecimalCal(a2, a1, b.charAt(0)));
//                        System.out.println("数字栈更新:"+number);
                    }
                    operator.push(temp);
//                    System.out.println("符号栈更新:"+operator);
                }
            }else {//遇到数字,直接压入数字栈
                number.push(new BigDecimal(temp));
//                System.out.println("数字栈更新:"+number);
            }
        }

        while(operator.peek()!=null) {//遍历结束后,符号栈数字栈依次弹栈计算,并将结果压入数字栈
            BigDecimal a1 = number.pop();
            BigDecimal a2 = number.pop();
            String b = operator.pop();
//            System.out.println("符号栈更新:"+operator);
//            System.out.println("数字栈更新:"+number);
//            System.out.println("计算"+a2+b+a1);
            number.push(BigDecimalCal(a2, a1, b.charAt(0)));
//            System.out.println("数字栈更新:"+number);
        }
        //System.out.println("值="+number.pop()+"");
        BigDecimal pop = number.pop().setScale(2,BigDecimal.ROUND_HALF_UP);//科学计数,保留2位小数
//        System.out.println(pop.toPlainString());
        return pop.toPlainString();//数值完全显示
       
       /*
        NumberFormat nf = NumberFormat.getInstance();   
        nf.setGroupingUsed(false);  
        String format = nf.format(pop);//科学计数转换成完全显示
        return format;
        */
       // return number.pop()+"";
    }

	
	@SuppressWarnings("null")
	public static void main(String[] args) throws Exception {
//        String str = "0.000000001";
//        str="0.0000001/10000000000";
//        System.out.println(getResult(str));
		String str="1.001";
        BigDecimal a=new BigDecimal(str);
        System.out.println(a.toPlainString());
        
        Double b=Double.valueOf("1.001");
        BigDecimal bb=new BigDecimal(Double.toString(b));
        System.out.println(bb.toPlainString());
       
        BigDecimal cc=new BigDecimal(Double.toString(b));
        System.out.println(cc.toPlainString());
        
        Double d=10000.994;
        DecimalFormat df = new DecimalFormat("#,###.00");
        System.out.println(df.format(d));
        
        BigDecimal bb1=new BigDecimal("2000000.00");
        BigDecimal bb2=new BigDecimal("1999999.999");
        BigDecimal subtract = bb2.subtract(bb1);
        System.out.println(subtract.toPlainString());
       if( subtract.compareTo(BigDecimal.ZERO)==-1){//小于
    	   System.out.println("负");
       }else if( subtract.compareTo(BigDecimal.ZERO)==1){//大于
    	   System.out.println("正");
       }else{//==0等于
    	   System.out.println("0");
       }
        
        Double valueOf = Double.valueOf(1999999.999-2000000.00);
        System.out.println(BigDecimal.valueOf(valueOf).toPlainString());
        
        BigDecimal decimalD=BigDecimal.valueOf(10000.99);
        System.out.println(BigDecimal.valueOf(10000.99).toPlainString());
        System.out.println(decimalD.toPlainString());
        System.out.println(df.format(decimalD));
        
        Double valueOf2 = Double.valueOf("10000000.999");
        BigDecimal de=BigDecimal.valueOf(valueOf2);
        System.out.println(de.toPlainString());
        BigDecimal de2 = new BigDecimal(Double.toString(valueOf2));
        System.out.println(de2.toPlainString());
        BigDecimal de3 = new BigDecimal(valueOf2);
        System.out.println(de3.toPlainString());
        System.out.println(de.doubleValue());
        
        BigDecimal v=new BigDecimal("-0.1");
        if( v.compareTo(BigDecimal.ZERO)==-1){//小于
     	   System.out.println("负");
        }else if( v.compareTo(BigDecimal.ZERO)==1){//大于
     	   System.out.println("正");
        }else{//==0等于
     	   System.out.println("0");
        }
        
        
        String aa=" 123 456 ";
        String trim = aa.trim();
        System.out.println(trim);
        
        String ab=null;
        String trim2 = ab.trim();//报空指针异常
        System.out.println(trim2);
        
      
    }

	
}

数据类型为double,会有精度丢失

package com.nantian.iwap.app.util;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 公式运算
 * */
public class SZYSUtils_1 {

	private static double doubleCal(double a1, double a2, char operator) throws Exception {
        switch (operator) {
        case '+':
            return a1 + a2;
        case '-':
            return a1 - a2;
        case '*':
            return a1 * a2;
        case '/':
            return a1 / a2;
        default:
            break;
        }
        throw new Exception("illegal operator!");
    }

	private static int getPriority(String s) throws Exception {
        if(s==null) return 0;
        else if(s.equals("(")) return 1;
        else if(s.equals("+") || s.equals("-")) return 2;
        else if(s.equals("*") || s.equals("/")) return 3;
        
        /*
        switch(s) {
        case "(":return 1;
        case "+":;
        case "-":return 2;
        case "*":;
        case "/":return 3;
        default:break;
        }
        */
        
        throw new Exception("illegal operator!");
    }

	public static String getResult(String expr) throws Exception {
        System.out.println("计算"+expr);
        /*数字栈*/
        Stack<Double> number = new Stack<Double>(); 
        /*符号栈*/
        Stack<String> operator = new Stack<String>();
        operator.push(null);// 在栈顶压人一个null,配合它的优先级,目的是减少下面程序的判断

        /* 将expr打散为运算数和运算符 */
        Pattern p = Pattern.compile("(?<!\\d)-?\\d+(\\.\\d+)?|[+\\-*/()]");// 这个正则为匹配表达式中的数字或运算符
        Matcher m = p.matcher(expr);
        while(m.find()) {
            String temp = m.group();
            if(temp.matches("[+\\-*/()]")) {//遇到符号
                if(temp.equals("(")) {//遇到左括号,直接入符号栈
                    operator.push(temp);
                    //System.out.println("符号栈更新:"+operator);
                }else if(temp.equals(")")){//遇到右括号,"符号栈弹栈取栈顶符号b,数字栈弹栈取栈顶数字a1,数字栈弹栈取栈顶数字a2,计算a2 b a1 ,将结果压入数字栈",重复引号步骤至取栈顶为左括号,将左括号弹出
                    String b = null;
                    while(!(b = operator.pop()).equals("(")) {
                        //System.out.println("符号栈更新:"+operator);
                        double a1 = number.pop();
                        double a2 = number.pop();
                       // System.out.println("数字栈更新:"+number);
                        //System.out.println("计算"+a2+b+a1);
                        number.push(doubleCal(a2, a1, b.charAt(0)));
                        //System.out.println("数字栈更新:"+number);
                    }
                    //System.out.println("符号栈更新:"+operator);
                }else {//遇到运算符,满足该运算符的优先级大于栈顶元素的优先级压栈;否则计算后压栈
                    while(getPriority(temp) <= getPriority(operator.peek())) {
                        double a1 = number.pop();
                        double a2 = number.pop();
                        String b = operator.pop();
                        //System.out.println("符号栈更新:"+operator);
                        //System.out.println("数字栈更新:"+number);
                        //System.out.println("计算"+a2+b+a1);
                        number.push(doubleCal(a2, a1, b.charAt(0)));
                        //System.out.println("数字栈更新:"+number);
                    }
                    operator.push(temp);
                    //System.out.println("符号栈更新:"+operator);
                }
            }else {//遇到数字,直接压入数字栈
                number.push(Double.valueOf(temp));
                //System.out.println("数字栈更新:"+number);
            }
        }

        while(operator.peek()!=null) {//遍历结束后,符号栈数字栈依次弹栈计算,并将结果压入数字栈
            double a1 = number.pop();
            double a2 = number.pop();
            String b = operator.pop();
            //System.out.println("符号栈更新:"+operator);
            //System.out.println("数字栈更新:"+number);
            //System.out.println("计算"+a2+b+a1);
            number.push(doubleCal(a2, a1, b.charAt(0)));
            //System.out.println("数字栈更新:"+number);
        }
       // System.out.println("值="+number.pop()+"");
        Double pop = number.pop();//科学计数
        NumberFormat nf = NumberFormat.getInstance();   
        nf.setGroupingUsed(false);  
        String format = nf.format(pop);//科学计数转换成完全显示
        return format;
       // return number.pop()+"";
    }

	
	public static void main(String[] args) throws Exception {
        String str = "-3.5*(4.5-(4+(-1-1/2)))";
        str="(1.4-1)*3-5*(2.1-1)";
        System.out.println(getResult(str));
        
        
    }

	
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值