• 后缀表达式总结



    一、后缀表达式介绍


    后缀表达式的特点就是计算机运算非常方便,需要用到栈;计算机处理过程只需要顺序读入,如果遇到数字,则放入栈中,如果是运算符,则将两个栈中数字取出进行运算;

    比如1+2的后缀表达式为12+;

    而栈可以把一般的中缀表达式变成后缀表达式,并且计算后缀表达式得出结果,因此此应用在计算器中非常常用;


    二、中缀表达式转换成后缀表达式


    此方法需要遵循几个规则:

    (1)如果读入操作数,则直接放入输出字符串;

    (2)如果读入一般运算符如+-*/,则放入堆栈,但是放入堆栈之前必须要检查栈顶,并确定栈顶运算符的优先级比放入的运算符的优先级低;如果放入的优先级较低,则需要将栈顶的运算符放入输出字符串;

    (3)如果读入(,因为左括号优先级最高,因此放入栈中,但是注意,当左括号放入栈中后,则优先级最低;

    (4)如果读入),则将栈中运算符取出放入输出字符串,直到取出(为止,注意:()不输出到输出字符串;

    (5)顺序读完表达式,如果栈中还有操作符,则弹出,并放入输出字符串;

      

    三、计算后缀表达式



    规则如下:

    (1)如果是操作数,则放入栈中;

    (2)如果是操作符,则取出栈中两个操作数,进行运算后,将结果放入栈中;

    (3)直到最后栈中只有一个元素,此元素就是计算结果;

    四、代码


    以下代码是计算器的辅助代码,通过此代码可以快速进行计算。

    输入: 四则运算(支持括号)

    输出:结果字符串


    package org.xiazdong.Calculatorutils;
    
    import java.util.Stack;
    
    
    
    /**
     * 计算器工具类
     * 完成整数、浮点的加、减、乘、除、括号运算
     * 
     * 禁忌:如果出现.5表示0.5,则结果不正确
     * @author xiazdong
     *
     */
    public class CalculatorUtils {
    	/**
    	 * 将中缀表达式转换成后缀表达式 规则: 1.如果是操作数,则添加到输出流 2.如果是(,则添加栈中;
    	 * 3.如果是),则将栈中操作符移入输出流,直到(为止,()不添加入输出流 4.如果是一般操作符(+-*
    	 * /),则加入栈之前,需要检查栈中的操作符的优先级,如果栈顶优先级比添加的优先级高,则将栈顶操作符移入输出流,否则直接添加操作符;
    	 */
    	
    	public static String calculate(String str){
    		return calculateReversePolish(exchangeToReversePolish(str));
    	}
    	
    	private static String exchangeToReversePolish(String str) {
    		// 1.创建Stack
    		Stack<String> s = new Stack<String>();
    		// 2.创建输出流字符串
    		StringBuilder builder = new StringBuilder();
    		// 3.解析中缀表达式
    		// 3.1 如果是读到数字,则接着读,直到读到操作符为止
    		for (int i = 0, numLenCount = 1; i < str.length(); i += numLenCount) {
    			char ch = str.charAt(i);
    			String operand = ch + "";
    			numLenCount = 1;
    			if ((ch + "").matches("\\d{1}")) {
    				numLenCount = 1;
    				char nextChar = 0;
    				if ((i + numLenCount) < str.length()) { // 下一个字符是否超过边界长度
    					nextChar = str.charAt(i + numLenCount);
    					while ((nextChar + "").matches("[.\\d{1}]")) {
    						operand += nextChar;
    						if ((i + numLenCount + 1) < str.length()) {
    							nextChar = str.charAt(i + numLenCount + 1);
    							numLenCount++;
    						} else {
    							numLenCount++;
    							break;
    						}
    					}
    				}
    				operand += " ";
    				builder.append(operand);
    
    			} else {
    				if (ch == '(') {
    					s.push(ch + "");
    				} else if (ch == '+' || ch == '-') {
    					while (s.size() > 0 && s.peek().matches("[-+*/]")) {
    						builder.append(s.pop() + " ");
    					}
    					s.push(ch + "");
    				} else if (ch == '*' || ch == '/') {
    					while (s.size() > 0 && s.peek().matches("[*/]")) {
    						builder.append(s.pop() + " ");
    					}
    					s.push(ch + "");
    				} else if (ch == ')') {
    					while (s.size() > 0 && !s.peek().equals("(")) {
    						builder.append(s.pop() + " ");
    					}
    					s.pop();
    				}
    			}
    		}
    		while (s.size() > 0) {
    			builder.append(s.pop() + " ");
    		}
    		System.out.println(builder);
    		return builder.toString();
    
    	}
    
    	/**
    	 * 计算后缀表达式
    	 * 
    	 */
    	private static String calculateReversePolish(String str) {
    
    		String[] splitStr = str.split(" ");
    		Stack<String> s = new Stack<String>();
    		for (int i = 0; i < splitStr.length; i++) {
    			String ch = splitStr[i];
    			if (ch.matches("\\d+.\\d+")||ch.matches("\\d+")) {
    				s.push(ch);
    			} else {
    				if (s.size() >= 2) {
    					String c1 = s.pop();
    					String c2 = s.pop();
    					if (ch.equals("+")) {
    						if(c1.contains(".")||c2.contains(".")){
    							s.push(String.valueOf((Double.parseDouble(c2 + "") + Double
    								.parseDouble(c1 + ""))));
    						}
    						else{
    							s.push(String.valueOf((Integer.parseInt(c2 + "") + Integer
    									.parseInt(c1 + ""))));
    						}
    						
    					} else if ("-".equals(ch)) {
    						if(c1.contains(".")||c2.contains(".")){
    						s.push(String.valueOf((Double.parseDouble(c2 + "") - Double
    								.parseDouble(c1 + ""))));
    						}
    						else{
    							s.push(String.valueOf((Integer.parseInt(c2 + "") - Integer
    									.parseInt(c1 + ""))));
    						}
    					} else if ("*".equals(ch)) {
    						if(c1.contains(".")||c2.contains(".")){
    						s.push(String.valueOf((Double.parseDouble(c2 + "") * Double
    								.parseDouble(c1 + ""))));
    						}
    						else{
    							s.push(String.valueOf((Integer.parseInt(c2 + "") * Integer
    									.parseInt(c1 + ""))));
    						}
    					} else if ("/".equals(ch)) {
    						s.push(String.valueOf((Double.parseDouble(c2 + "") / Double
    								.parseDouble(c1 + ""))));
    					}
    
    				} else {
    					System.out.println("式子有问题!");
    					return null;
    				}
    			}
    		}
    		return s.pop();
    	}
    }
    








    作者:xiazdong
    出处:http://blog.xiazdong.info
    本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。
  • 相关阅读:
    day19(上)_IO流2(BufferedReaer,BufferedWriter,BufferedInputStream,BufferedOutputStream)
    day19(下)_IO流4(InputStreamReader,OutputStreamWriter,流操作规律总结)
    Synchronized锁 IT
    Linux查看端口信息命令 IT
    ReentrantLock锁 IT
    让网站实时生成多种电子书:jar、umd、chm、pdf、epub
    mysql性能的检查和调优方法
    新型的大型bbs架构(squid+nginx)
    uchome中的防反复提交机制
    joymobiler V2.7发布,支持pdf文档的生成
  • 原文地址:https://www.cnblogs.com/xiazdong/p/3058075.html
Copyright © 2020-2023  润新知