`
chengpan
  • 浏览: 43569 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

混合运算 后缀表达式算法实现

阅读更多

因为要用到四则混合运算,写了一个工具类,是基于后缀表达式的实现

 

package com.eden.door.util;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;



/**
 * 处理四则混合运算 , 支持负数+,-,*,/,%,^,括号
 * @author Eden
 *
 */
public class Calculator {
	private static Calculator instance = new Calculator() ;
	
	private String operators = "+-*/%^()#" ;
	
	//运算符栈外优先级
	private Map<String, Integer> icp = null ;
	//运算符栈内优先级
	private Map<String, Integer> isp = null ;
	
	public static Calculator newInstance(){
		return instance ;
	}
	
	public Calculator(){
		icp = new HashMap<String, Integer>();
		isp = new HashMap<String, Integer>();
		
		icp.put("#", 0) ;
		icp.put(")", 1) ;
		icp.put("+", 2) ;
		icp.put("-", 2) ;
		icp.put("*", 4) ;
		icp.put("/", 4) ;
		icp.put("%", 4) ;
		icp.put("^", 6) ;
		icp.put("(", 8) ;
		
		isp.put("#", 0) ;
		isp.put("(", 1) ;
		isp.put("+", 3) ;
		isp.put("-", 3) ;
		isp.put("*", 5) ;
		isp.put("/", 5) ;
		isp.put("%", 5) ;
		isp.put("^", 7) ;
		isp.put(")", 8) ;
	}
	/**
	 * 格式化表达式  ,有符号的,在前面加上0
	 * 例如(-2) + 3 格式化之后 (0-2) + 3
	 * @param exp 
	 * @return
	 */
	protected String formatExp(String exp) {
		
		String sign = "+-" ;
		StringBuilder sbExp = new StringBuilder(exp.trim().replace(" ", "")) ;
		
		if(sign.contains(sbExp.subSequence(0, 1))){
			sbExp.insert(0, "0") ;
		}
		for(int i = 0; i < sbExp.length(); i++) {
			if(sbExp.charAt(i) == '('){
				if(sign.contains(String.valueOf(sbExp.charAt(i+1)))){
					sbExp.insert(i+1, "0") ;
				}
			}
		}
		return sbExp.toString() ;
	}
	
	/**
	 * 判断字符是否为运算符
	 * @param c
	 * @return
	 */
	protected boolean isOperator(char c) {
		if(operators.contains(String.valueOf(c)))
			return true ;
		return false ;
	}
	protected boolean isOperator(String s){
		if(operators.contains(s))
			return true ;
		return false ;
	}
	

	
	/**
	 * 优先级的比较 
	 * @param currOp 当前运算符
	 * @param preOp 栈顶运算符
	 * @return 
	 * 当前运算符 > 栈顶运算符 返回 -1  
	 * 当前运算符 = 栈顶运算符 返回 0  
	 * 当前运算符 < 栈顶运算符 返回1 
	 */
	protected int opComp(String currOp , String preOp) {
		
		int currPriority = icp.get(currOp) ;
		int prePriority = isp.get(preOp) ;
		
		if( prePriority > currPriority )
			return 1 ;
		else if ( prePriority == currPriority ) {
			return 0;
		} else
			return -1 ;
	}
	
	/**
	 * 中缀表达式转换为后缀表达式
	 * @param infix
	 * @return
	 */
	protected List<String> infix2Postfix(String infix){
		List<String> postfixList = new ArrayList<String>() ;
		
		List<String> infixList = infixStr2List(infix) ;
		Deque<String> opStack = new ArrayDeque<String>() ;
		
		
		String str = "" ;
		for(int i = 0 ; i < infixList.size() ; i++){
			str = infixList.get(i) ;
			
			if(isOperator(str)){
				
				if( "(".equals(str) ){
					opStack.push(str) ;
				} 
				else if( ")".equals(str) ){
					while(!"(".equals(opStack.peek()) ){
						postfixList.add(opStack.pop()) ;
					}
					opStack.pop() ;
				}
				
				else if(opStack.peek() == null){
					opStack.push(str) ;
				} else {
					//如果栈顶运算符优先级比当前运算符优先级低将栈顶运算符弹邮放到后缀表达式中
					while( opStack.peek()!= null && opComp(str , opStack.peek()) >= 0 ){
						postfixList.add(opStack.pop()) ;
					}
					if(opStack.peek() == null){
						opStack.push(str) ;
					} 
					//如果栈顶运算符优先级比当前运算符优先级高压到后缀表达式中
					else if ( opComp(str , opStack.peek()) == -1 ) {
						opStack.push(str) ;
					}
				}
			} else {
				postfixList.add(str) ;
			}
		}
		//最后把栈中的运算符加到后缀表达式中
		while(opStack.peek() != null){
			postfixList.add(opStack.pop()) ;
		}
		
		return postfixList ;
	}
	
	/**
	 * 将中缀表达式字符串转换为中缀List
	 * @param infix
	 * @return
	 */
	protected List<String> infixStr2List(String infix){
		List<String> infixList = new ArrayList<String>() ;
		int start = 0 ;
		for(int i = 0 ; i < infix.length() ; i++){
			if(isOperator(infix.charAt(i)) ){
				if(i - start > 0){
					//截取两个运算 符之间的数字
					infixList.add(infix.substring(start , i) ) ;
				}
				start = i+1 ;
				//将运算符放到中缀表达式中
				infixList.add(infix.substring(i, i+1)) ;
			}
		}
		
		//如果最 后一位为数字
		if(start<infix.length()){
			infixList.add(infix.substring(start)) ;
		}
		return infixList ;
	}
	/**
	 * 计算运算表达式
	 * @param expression
	 * @return
	 */
	public double calculate(String expression) {
		//格式化运算式
		String infix = this.formatExp(expression) ;
		//求出中缀表达式
		List<String> infixList = infixStr2List(infix) ; 
		//得出后缀表达式
		List<String> postfixList = infix2Postfix(infix) ;
		
		System.out.println(infix) ;
		System.out.println(infixList) ;
		System.out.println(postfixList) ;
		
		//计算后缀表达式
		double r = computePostfix(postfixList) ;
		
		return r ;
	}
	
	/**
	 * 对后缀表达式求值
	 * @param postfixList
	 * @return
	 */
	protected double computePostfix(List<String> postfixList) {
		Deque<Double> rsStack = new ArrayDeque<Double>() ;
		
		double r = 0 ;
		for(String item : postfixList) {
			if(!isOperator(item)){
				rsStack.push(Double.parseDouble(item)) ;
			} else {
				double num1 = rsStack.pop() ;
				double num2 = rsStack.pop() ;
				
				if("+".equals(item)){
					r = num2 + num1 ;
				} else if("-".equals(item)){
					r = num2 - num1 ;
				} else if("*".equals(item)){
					r = num2 * num1 ;
				} else if("/".equals(item)){
					r = num2 / num1 ;
				} else if("%".equals(item)){
					r = num2 % num1 ;
				} else if("^".equals(item)){
					r = Math.pow(num2, num1) ;
				}
				
				rsStack.push(r) ;
			}
		}
		
		return rsStack.pop() ;
	}
	
	//测试
	public static void main(String[] args){
		
		String exp = "1/(0.3243e3) * ((-20 + 28) + (2 + 2))" ;
		
//		System.out.println( System.currentTimeMillis()) ;
		System.out.println(Calculator.newInstance().calculate(exp) ) ;
//		System.out.println( System.currentTimeMillis() ) ;
	}
}
 

        for(String item : postfixList) {
            if(!isOperator(item)){
                rsStack.push(Double.parseDouble(item)) ;
            } else {
                double num1 = rsStack.pop() ;
                double num2 = rsStack.pop() ;
               
                if("+".equals(item)){
                    r = num2 + num1 ;
                } else if("-".equals(item)){
                    r = num2 - num1 ;
                } else if("*".equals(item)){
                    r = num2 * num1 ;
                } else if("/".equals(item)){
                    r = num2 / num1 ;
                } else if("%".equals(item)){
                    r = num2 % num1 ;
                } else if("^".equals(item)){
                    r = Math.pow(num2, num1) ;
                }
               
                rsStack.push(r) ;
            }
        }
       
        return rsStack.pop() ;
    }
   
    //测试
    public static void main(String[] args){
       
        String exp = "1/(0.3243e3) * ((-20 + 28) + (2 + 2))" ;
       
//        System.out.println( System.currentTimeMillis()) ;
        System.out.println(Calculator.newInstance().calculate(exp) ) ;
//        System.out.println( System.currentTimeMillis() ) ;
    }
}

分享到:
评论

相关推荐

    四则混合运算的算法

    此算法用于四则运算,没有对异常进行处理。 输入形式请如下: A+(B+C)*D= ((B+C)*D+(A+F)/E)+G/H+W= 记得输入等号,本人没有考虑回车的情况,请自行修改。 文件arithmeic主要用于将中缀表达式转为后缀表达式。 cal_...

    数据结构大作业C++实现简单的计算器——算术表达式计算(包含实验报告)

    利用运算符优先关系,实现对算术四则混合运算表达式的求值。 【测试数据】 (1)能够判断表达式中的括号是否匹配,测试的表达式中括号不匹配,可以重新输入。 (2)能够处理多位整数以及浮点数。 (3)具体测试数据...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    2.5.3 表达式中各类数值型数据间的混合运算 2.5.4 自增和自减运算符 2.5.5 强制类型转换运算符 2.6 赋值运算符与赋值表达式 2.6.1 赋值运算符 2.6.2 赋值过程中的类型转换 2.6.3 复合的赋值运算符 2.6.4 赋值表达式 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar

    2.5.3 表达式中各类数值型数据间的混合运算 2.5.4 自增和自减运算符 2.5.5 强制类型转换运算符 2.6 赋值运算符与赋值表达式 2.6.1 赋值运算符 2.6.2 赋值过程中的类型转换 2.6.3 复合的赋值运算符 2.6.4 赋值表达式 ...

    C语言从入门到精通必备资料

    3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 3 3.10 逗号运算符和逗号表达式 48 3.11 小结 49 ...

    谭浩强C语言word版

    3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号表达式 18 3.11 小结 19 3.11.1 ...

    谭浩强 入门c语言教程

    3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号表达式 18 3.11 小结 19 3.11.1 ...

    谭浩强C程序设计第三版

    各类数值型数据之间的混合运算 49 算术运算符和算术表达式 51 C运算符简介 51 算术运算符和算术表达式 51 赋值运算符和赋值表达式 53 逗号运算符和逗号表达式 55 小结 55 C的数据类型 55 基本类型的分类及特点 55 ...

    《C语言程序设计》谭浩强

    3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 3 3.10 逗号运算符和逗号表达式 48 3.11 小结 49 ...

    谭浩强版c语言程序设计

    3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 3 3.10 逗号运算符和逗号表达式 48 3.11 小结 49 ...

    谭浩强c语言word版

    3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 3 3.10 逗号运算符和逗号表达式 48 3.11 小结 49 ...

    谭浩强c语言程序设计

    3.7 各类数值型数据之间的混合运算 43 3.8 算术运算符和算术表达式 44 3.8.1 C运算符简介 44 3.8.2 算术运算符和算术表达式 45 3.9 赋值运算符和赋值表达式 47 3 3.10 逗号运算符和逗号表达式 48 3.11 小结 49 ...

    谭浩强 C语言程序设计 教程全书 Word版

    3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号表达式 18 3.11 小结 19 3.11.1 ...

    c语言程序设计(第三版)

    3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号表达式 18 3.11 小结 19 3.11.1 ...

    c语言(编写程序最佳参考资料)

    3.7 各类数值型数据之间的混合运算... 13 3.8 算术运算符和算术表达式... 14 3.8.1 C运算符简介... 14 3.8.2 算术运算符和算术表达式... 15 3.9 赋值运算符和赋值表达式... 17 3.10 逗号运算符和逗号表达式... ...

    谭浩强C语言教程Word版

    12 3.7 各类数值型数据之间的混合运算 13 3.8 算术运算符和算术表达式 14 3.8.1 C运算符简介 14 3.8.2 算术运算符和算术表达式 15 3.9 赋值运算符和赋值表达式 17 3.10 逗号运算符和逗号...

    Java开发技术大全(500个源代码).

    sign.java 用条件运算实现符号函数示例 signByIF.java 用if语句实现符号函数示例 triangleStar.java 输出一个由*组成的直角三角形 upperToLowCase.java 大写转换成小写 variableScopeExample.java 变量使用范围...

    易语言 茶凉专用模块

    模块名称:茶凉专用模块 作者:茶凉 版本:2.0 本模块可以编程更简单,仅仅用核心支持库编写。 @备注: ...官方QQ群:92716369 ------------------------ -------------------------- ...------------------------------ ...

Global site tag (gtag.js) - Google Analytics