zoukankan      html  css  js  c++  java
  • 逆波兰计算器完整版

    逆波兰计算器完整版

      完整版的逆波兰计算器,功能包括:

      (1)支持+,-,*,/,()

      (2)支持多位数,支持小数

      (3)兼容处理,过滤任何空白字符,包括空格、制表符,换页符

      代码实现:

      1 import java.util.ArrayList;
      2 import java.util.Collections;
      3 import java.util.List;
      4 import java.util.Stack;
      5 import java.util.regex.Pattern;
      6 
      7 public class ReversePolishMultiCalc {
      8 
      9      /**
     10      * 匹配 + - * / ( ) 运算符
     11      */
     12     static final String SYMBOL = "\+|-|\*|/|\(|\)";
     13 
     14     static final String LEFT = "(";
     15     static final String RIGHT = ")";
     16     static final String ADD = "+";
     17     static final String MINUS= "-";
     18     static final String TIMES = "*";
     19     static final String DIVISION = "/";
     20 
     21     /**
     22      * 加減 + -
     23      */
     24     static final int LEVEL_01 = 1;
     25     /**
     26      * 乘除 * /
     27      */
     28     static final int LEVEL_02 = 2;
     29 
     30     /**
     31      * 括号
     32      */
     33     static final int LEVEL_HIGH = Integer.MAX_VALUE;
     34 
     35 
     36     static Stack<String> stack = new Stack<>();
     37     static List<String> data = Collections.synchronizedList(new ArrayList<String>());
     38 
     39     /**
     40      * 去除所有空白符
     41      * @param s
     42      * @return
     43      */
     44     public static String replaceAllBlank(String s ){
     45         // \s+ 匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[ f
    
    	v]
     46         return s.replaceAll("\s+","");
     47     }
     48 
     49     /**
     50      * 判断是不是数字 int double long float
     51      * @param s
     52      * @return
     53      */
     54     public static boolean isNumber(String s){
     55         Pattern pattern = Pattern.compile("^[-\+]?[.\d]*$");
     56         return pattern.matcher(s).matches();
     57     }
     58 
     59     /**
     60      * 判断是不是运算符
     61      * @param s
     62      * @return
     63      */
     64     public static boolean isSymbol(String s){
     65         return s.matches(SYMBOL);
     66     }
     67 
     68     /**
     69      * 匹配运算等级
     70      * @param s
     71      * @return
     72      */
     73     public static int calcLevel(String s){
     74         if("+".equals(s) || "-".equals(s)){
     75             return LEVEL_01;
     76         } else if("*".equals(s) || "/".equals(s)){
     77             return LEVEL_02;
     78         }
     79         return LEVEL_HIGH;
     80     }
     81 
     82     /**
     83      * 匹配
     84      * @param s
     85      * @throws Exception
     86      */
     87     public static List<String> doMatch (String s) throws Exception{
     88         if(s == null || "".equals(s.trim())) throw new RuntimeException("data is empty");
     89         if(!isNumber(s.charAt(0)+"")) throw new RuntimeException("data illeagle,start not with a number");
     90 
     91         s = replaceAllBlank(s);
     92 
     93         String each;
     94         int start = 0;
     95 
     96         for (int i = 0; i < s.length(); i++) {
     97             if(isSymbol(s.charAt(i)+"")){
     98                 each = s.charAt(i)+"";
     99                 //栈为空,(操作符,或者 操作符优先级大于栈顶优先级 && 操作符优先级不是( )的优先级 及是 ) 不能直接入栈
    100                 if(stack.isEmpty() || LEFT.equals(each)
    101                         || ((calcLevel(each) > calcLevel(stack.peek())) && calcLevel(each) < LEVEL_HIGH)){
    102                     stack.push(each);
    103                 }else if( !stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())){
    104                     //栈非空,操作符优先级小于等于栈顶优先级时出栈入列,直到栈为空,或者遇到了(,最后操作符入栈
    105                     while (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek()) ){
    106                         if(calcLevel(stack.peek()) == LEVEL_HIGH){
    107                             break;
    108                         }
    109                         data.add(stack.pop());
    110                     }
    111                     stack.push(each);
    112                 }else if(RIGHT.equals(each)){
    113                     // ) 操作符,依次出栈入列直到空栈或者遇到了第一个)操作符,此时)出栈
    114                     while (!stack.isEmpty() && LEVEL_HIGH >= calcLevel(stack.peek())){
    115                         if(LEVEL_HIGH == calcLevel(stack.peek())){
    116                             stack.pop();
    117                             break;
    118                         }
    119                         data.add(stack.pop());
    120                     }
    121                 }
    122                 start = i ;    //前一个运算符的位置
    123             }else if( i == s.length()-1 || isSymbol(s.charAt(i+1)+"") ){
    124                 each = start == 0 ? s.substring(start,i+1) : s.substring(start+1,i+1);
    125                 if(isNumber(each)) {
    126                     data.add(each);
    127                     continue;
    128                 }
    129                 throw new RuntimeException("data not match number");
    130             }
    131         }
    132         //如果栈里还有元素,此时元素需要依次出栈入列,可以想象栈里剩下栈顶为/,栈底为+,应该依次出栈入列,可以直接翻转整个stack 添加到队列
    133         Collections.reverse(stack);
    134         data.addAll(new ArrayList<>(stack));
    135 
    136         System.out.println(data);
    137         return data;
    138     }
    139 
    140     /**
    141      * 算出结果
    142      * @param list
    143      * @return
    144      */
    145     public static Double doCalc(List<String> list){
    146         Double d = 0d;
    147         if(list == null || list.isEmpty()){
    148             return null;
    149         }
    150         if (list.size() == 1){
    151             System.out.println(list);
    152             d = Double.valueOf(list.get(0));
    153             return d;
    154         }
    155         ArrayList<String> list1 = new ArrayList<>();
    156         for (int i = 0; i < list.size(); i++) {
    157             list1.add(list.get(i));
    158             if(isSymbol(list.get(i))){
    159                 Double d1 = doTheMath(list.get(i - 2), list.get(i - 1), list.get(i));
    160                 list1.remove(i);
    161                 list1.remove(i-1);
    162                 list1.set(i-2,d1+"");
    163                 list1.addAll(list.subList(i+1,list.size()));
    164                 break;
    165             }
    166         }
    167         doCalc(list1);
    168         return d;
    169     }
    170 
    171     /**
    172      * 运算
    173      * @param s1
    174      * @param s2
    175      * @param symbol
    176      * @return
    177      */
    178     public static Double doTheMath(String s1,String s2,String symbol){
    179         Double result ;
    180         switch (symbol){
    181             case ADD : result = Double.valueOf(s1) + Double.valueOf(s2); break;
    182             case MINUS : result = Double.valueOf(s1) - Double.valueOf(s2); break;
    183             case TIMES : result = Double.valueOf(s1) * Double.valueOf(s2); break;
    184             case DIVISION : result = Double.valueOf(s1) / Double.valueOf(s2); break;
    185             default : result = null;
    186         }
    187         return result;
    188 
    189     }
    190 
    191     public static void main(String[] args) {
    192         //String math = "9+(3-1)*3+10/2";
    193         String math = "12.8 + (2 - 3.55)*4+10/5.0";
    194         try {
    195             doCalc(doMatch(math));
    196         } catch (Exception e) {
    197             e.printStackTrace();
    198         }
    199     }
    200 
    201 }
  • 相关阅读:
    C#.NET实现DES对称加密
    C#.NET 比较好用的tcp通信模板(服务器端篇)
    追MM的二十三种方法
    C# .NET锁屏程序(顺带屏蔽任务管理器)
    近段时间个人总结
    C#.NET 比较好用的tcp通信模板(客户端篇)
    使用BufferedReader读取文本内容
    map集合增强for循环遍历后输出文本
    流程控制
    centos7安装golang
  • 原文地址:https://www.cnblogs.com/niujifei/p/11603042.html
Copyright © 2011-2022 走看看