用栈的技术来实现计算器的功能

6 篇文章 0 订阅
1 篇文章 0 订阅

 

使用栈实现一个综合的计算器的功能,用户输入想要计算的表达式,然后进行计算,主要用到的技术是栈先进后出的特点。

package com.yu.datastructure.stack;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PolandNotation3 {

    public static void main(String[] args) {
        String exepression = "(7+(4*7)-1) + 7 -9 + 12 *5";
        List<String> list = toList(exepression);
        System.out.println("转换的集合:" + list);
        List<String> parseSuffixExpressionList = parseSuffixExpressionList(list);
        System.out.println("后缀表达式" +parseSuffixExpressionList);
        Double value = calculation(parseSuffixExpressionList);
        System.out.println("计算的结果:" + value);
    }
    
    /**
     * 去除表达式的空白符
     * @param str
     * @return
     */
    public static String replaceAllBlank(String str){
        // \\s+ 匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[\f\n\r\t\v]
        return str.replaceAll("\\s+","");
    }
    
    
    /**
     * 判断是否是数字的正则表达式,把点,百分号也算成数字
     * @param str
     * @return
     */
    public static boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("^?[.\\d]*?[%\\d]*$");
        Matcher isNum = pattern.matcher(str);
        if (!isNum.matches()) {
            return false;
        }
        return true;
    }
    
    /**
     * 判断是否是运算符的的正则表达式
     */
    public static boolean isSymbol(String str){
        
        return str.matches("\\+|\\-|\\*|\\/|\\(|\\)");
    }
    
    /**
     * 判断运算符的优先级
     */
    public static Integer operatorPriority(String str){
        if("*".equals(str) || "/".equals(str)) {
            return 2;
        }else if("+".equals(str) || "-".equals(str)) {
            return 1;
        }else{
            return -1;
        }
    }
    
    /**
     * 计算的表达式
     * @param s1 第一个值
     * @param s2 第二个值
     * @param symbol 计算的表达式
     * @return
     */
    public static Double calculation(String s1,String s2,String symbol){
        Double result = 0.0;
        switch (symbol) {
        case "+":
            result = Double.valueOf(s2) + Double.valueOf(s1);
            break;
        case "-":
            result = Double.valueOf(s2) - Double.valueOf(s1);
            break;
        case "*":
            result = Double.valueOf(s2) * Double.valueOf(s1);
            break;
        case "/":
            result = Double.valueOf(s2) / Double.valueOf(s1);
            break;
        default:
            throw new RuntimeException("计算出错");
        }
        return result;
    }
    
    /**
     * 将表达式的值放入到集合中
     */
    public static List<String> toList(String exepression){
        exepression = replaceAllBlank(exepression);
        if (exepression == null || exepression.trim().equals("")) {
            throw new RuntimeException("出具为空");
        }
        if(!isNumber(exepression.charAt(0) + "") && !(exepression.charAt(0) + "").equals("(")){
            throw new RuntimeException("表达式的第一个值不对,请检查");
        }
        List<String> list = new ArrayList<>();
        int index = 0;
        String data = "";
        String temp = "";//用于拼接数据
        while(true){
            if(!isNumber(data = exepression.charAt(index) + "")){
                list.add(data);
                index++;
            }else{
                while(index < exepression.length() && isNumber(data = exepression.charAt(index) + "")){
                    temp += data;
                    if(index >= exepression.length()){
                        break;
                    }
                    index++;
                }
                list.add(temp);
                temp = "";
            }
            if(index >= exepression.length()){
                break;
            }
        }
        return list;
    }
    
    /**
     * 将集合中的表达式转换为一个后缀表达式
     * @param list 传入的集合
     * 
     */
    public static List<String> parseSuffixExpressionList(List<String> expressionList) {
        if (expressionList.size() <= 0) {
            throw new RuntimeException("传入的数组为空,请检查");
        }
        Stack<String> stack = new Stack<>();// 用来存放符号的栈
        List<String> list = new ArrayList<>();// 用来存放数字和符号的集合
        for (String str : expressionList) {
            if (isNumber(str)) {
                // 如果是数字,则直接加入到集合
                list.add(str);
            } else {
                if (str.equals("(")) {
                    // 如果是左括号,直接入栈
                    stack.push(str);
                } else if (str.equals(")")) {
                    // 如果是右括号,则取出左边符号栈里面的符号,加入到集合里面,直到遇到符号栈里面的左括号,这样就可以消除一对括号了
                    while (!stack.peek().equals("(")) {
                        list.add(stack.pop());
                    }
                    // 消除左括号
                    stack.pop();
                } else {
                    // 如果当前取出的操作符的优先级小于等于栈顶的优先级,将栈顶的元素弹出加入到集合里面,持续到大于栈的数据,然后把当前取出的数据加入到栈
                    while (stack.size() != 0 && operatorPriority(str) <= operatorPriority(stack.peek())) {
                        list.add(stack.pop());
                    }
                    stack.push(str);
                }
            }
        }
        // 操作完成之后,然后把栈里面的数据依次加入到集合里面,集合遍历的数据就是后缀表达式
        while (stack.size() != 0) {
            list.add(stack.pop());
        }
        return list;
    }
    
    /**
     * 计算后缀表达式的值
     * 计算规则:如果遇到的是数字,依次入栈,如果符号,则取出栈里面的值来进行计算,
     * 计算之后将结果入栈,再讲数入栈,依次进行计算,最后栈里面的数据就是计算的结果
     * @param list
     */
    public static Double calculation(List<String> list){
        if(list.size() < 0){
            throw new RuntimeException("集合为空");
        }
        Stack<String> stack = new Stack<>();
        for (String str : list) {
            if(isNumber(str)){
                stack.push(str);
            }else{
                Double calculation = calculation(stack.pop(),stack.pop(),str);
                stack.push(calculation + "");
            }
        }
        return Double.parseDouble(stack.pop());
    }
}
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值