仿android计算器,实现了括号详解编程语言

  
package com.fire.utils; 
   
import java.text.DecimalFormat; 
import java.text.NumberFormat; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.StringTokenizer; 
   
/** 
 * 工具类 
 *  
 * @author FireAnt 
 * 
 */ 
public class Tools { 
       
    public static int i = 0; 
       
    /** 
     * 计算一个合法的表达式的值 
     * @param exp 
     * @return 
     */ 
    public static String cal(String exp) { 
           
        // 特殊表达式的处理方式 
        if (exp.length() == 0) { 
               
            return ""; 
        } else if (exp.length() == 1) { 
               
            if (exp.equals(".")) { 
                   
                return "0"; 
            } else { 
                   
                return ""; 
            } 
        } else if (exp.matches(".*÷0.*")) { // 0作为除数 
               
            return "∞"; 
        } else if (exp.matches(".*[+-/×÷]")) { 
               
            exp = exp.substring(0, exp.length() - 1); 
            if (exp.equals(".")) { 
                return "0"; 
            }    
        } 
           
        // 如果表达式中有括号则递归计算 
        if (exp.contains("(")) { 
               
            // 找出最后一个左括号 
            int left = exp.lastIndexOf("("); 
            // 找出第一个右括号 
            int right = exp.indexOf(")"); 
            // 获取第一个子表达式 
            String subExp = exp.substring(left + 1, right); 
            // 计算子表达式的结果 
            String res = cal(subExp);  
            // 用计算出来的结果替换子表达式 
            exp = exp.substring(0, left) + res + exp.substring(right + 1); 
            // 递归计算新的表达式 
            exp = cal(exp); 
        } 
           
        // 格式化表达式 
        String newExp = formatExp(exp); 
        List<Character> opts = getOptions(newExp); 
        List<Double> nums = getNums(newExp); 
           
        // 先处理乘除 
        for (int i = 0; i < opts.size(); i++) { 
               
            char opt = opts.get(i); 
            if (opt == '÷' || opt == '×') { 
                   
                opts.remove(i); 
                double d1 = nums.remove(i); 
                double d2 = nums.remove(i); 
                if (opt == '÷') { 
                       
                    d1 = d1 / d2; 
                       
                } else { 
                       
                    d1 = d1 * d2; 
                } 
                nums.add(i, d1); 
                i--; 
            } 
        } 
           
        while (!opts.isEmpty()) { 
               
            char opt = opts.remove(0); 
            double d1 = nums.remove(0); 
            double d2 = nums.remove(0); 
            if (opt == '+') { 
                d1 = d1 + d2; 
            } else { 
                d1 = d1 - d2; 
            } 
            nums.add(0, d1); 
        } 
           
        return formatNum(nums.get(0)); 
    } 
       
    /** 
     * 获得一个表达式中所有的运算符 
     * @param exp 
     * @return 
     */ 
    private static List<Character> getOptions(String exp) { 
           
        List<Character> opts = new ArrayList<Character>(); 
        StringTokenizer st = new StringTokenizer(exp, "@.0123456789"); 
        while (st.hasMoreTokens()) { 
               
            opts.add(st.nextToken().charAt(0)); 
        } 
        return opts; 
    } 
       
    /** 
     * 获得一个表达式中所有的数字 
     * @param exp 
     * @return 
     */ 
    private static List<Double> getNums(String exp) { 
           
        List<Double> nums = new ArrayList<Double>(); 
        StringTokenizer st = new StringTokenizer(exp, "+-×÷"); 
        while (st.hasMoreTokens()) { 
               
            String num = st.nextToken(); 
            if (num.contains("@")) { 
                   
                num = "-" + num.substring(1); 
            } 
            nums.add(Double.parseDouble(num)); 
        } 
        return nums; 
    } 
       
    /** 
     * 格式一个浮点数 
     * @param num 
     * @return 
     */ 
    public static String formatNum(double num) { 
           
        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance(); 
           
        df.applyLocalizedPattern("#0.##########"); 
        if (num > 1000000000) { 
               
            df.applyPattern("#0.#######E0"); 
        } 
           
        return df.format(num); 
    } 
       
    /** 
     * 格式化表达式 
     *  1.替换操作(找出负号,[email protected]) 
     *  2.避免非法表达式的出现 
     */ 
    private static String formatExp(String exp) { 
           
        // 如果表达式是以运算符结束的,则将最后一位运算符去除 
        if (exp.matches(".*[+-/×÷]")) { 
               
            exp = exp.substring(0, exp.length() - 1); 
        } 
        String res = exp; 
        if (exp.charAt(0) == '-') { 
               
            res = "@" + res.substring(1); 
        } 
           
        for (int i = 1; i < res.length(); i++) { 
               
            if (res.charAt(i) == '-' && (res.charAt(i - 1) == '÷' || res.charAt(i - 1) == '×')) { 
                   
                res = res.substring(0, i) + "@" + res.substring(i + 1); 
            } 
        } 
        return res; 
    } 
       
    /** 
     * 检查表达式是否有括号,并且检查是否符合 
     * @param exp 
     * @return 
     */ 
    public static boolean checkExp(String exp) { 
           
        boolean res = true; 
           
        int index = exp.indexOf("("); 
        if (index != -1) { 
               
            int leftN = 0; 
            for (int i = index; i < exp.length(); i++) { 
                   
                if (exp.charAt(i) == '(') { 
                    leftN++; 
                } 
                else if (exp.charAt(i) == ')') { 
                    leftN--; 
                    if (leftN == -1) { 
                        res = false; 
                        break; 
                    } 
                } 
            } 
            if (leftN > 0) { 
                   
                res = false; 
            } 
        } 
           
        return res; 
    } 
} 
  

原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/10665.html

(0)
上一篇 2021年7月19日 10:22
下一篇 2021年7月19日 10:22

相关推荐

发表回复

登录后才能评论