带括号的四则运算

带括号的四则运算

public class CaculatorDemo {

public static void main(String[] args) {
    String exp = "-3+6*-2-8/-4*2";//-11
    String exp2 = "-3+(9+8+(8-4)/2)*2";//35
    //double result = calc(exp);
    double result = calcKuohao(exp2);
    System.out.println(result);

    result = dkuohao(exp2);
    System.out.println(result);
}

/**
 * 带括号的四则运算
 * @param exp
 * @return
 */
public static double calcKuohao(String exp){
    //找最后一个左括号的下标,没找到就返回-1
    int left = exp.lastIndexOf('(');
    if (left == -1) {
        //说明表达式无括号
        return calc(exp);
    }else {
        //找与它相对应的右括号的下标
        int right = exp.indexOf(')', left);
        //找到相对应的右括号之后,取出括号中的表达式
        String str = exp.substring(left + 1, right);
        //对str做无括号四则运算
        double d = calc(str);
        //拼接
        exp = exp.substring(0, left) + d + exp.substring(right + 1);
        //递归去括号
        return calcKuohao(exp);
    }
}

/**
 * 不带括号的四则运算
 * @param exp
 * @return
 */
public static double calc(String exp){
    double result = 0;
    //将负号转换成@符号
    exp = fu2At(exp);
    //提取数字集合
    List<Double> nums = getNums(exp);
    //提取运算符集合
    List<Character> opts = getOpts(exp);
    //先乘除
    //遍历运算符集合,如果是*/就取出来
    for (int i = 0; i < opts.size(); i++) {
        char c = opts.get(i);
        if (c == '*' || c == '/') {
            opts.remove(i);//移除该运算符
            //从数字集合的i的位置取出第一个数
            double d1 = nums.remove(i);
            //再从数字集合的i的位置取出第二个数
            double d2 = nums.remove(i);
            //判断运算符到底是乘号还是除号
            if (c == '*') {
                d1 *= d2; 
            }else {
                d1 /= d2;
            }
            //将运算结果,放回数字集合的i的位置
            nums.add(i, d1);
            //为了避免i+1位置的乘除号被跳过。因为取出一个符号之后,后面的符号就会往前移动。
            i --;
        }
    }
    //for循环结束后,表示乘除法做完了,只剩下加减法,opts里面只有+-号
    //后加减,一直到所有运算符都被移除
    while(!opts.isEmpty()){
        //从运算符集合的0的位置取出运算符
        char opt = opts.remove(0);
        //从数字集合的0的位置取出第一个数
        double d1 = nums.remove(0);
        //从数字集合的0的位置取出第二个数
        double d2 = nums.remove(0);
        if (opt == '+') {
            d1 += d2;
        }else {
            d1 -= d2;
        }
        //将运算结果放回到数字集合的0的位置
        nums.add(0, d1);
    }
    //运算结束后,数字集合0的位置的值就是运算结果。
    result = nums.get(0);
    //后加减
    return result;
}

/**
 * 提取运算符集合
 * @param exp
 * @return
 */
private static List<Character> getOpts(String exp) {
    //定义一个集合来,存储运算符
    List<Character> opts = new ArrayList<>();
    //用来分隔字符串的api
    StringTokenizer sTokenizer = new StringTokenizer(exp, "0123456789.@");
    while(sTokenizer.hasMoreElements()){
        String strs = sTokenizer.nextElement().toString();
        opts.add(strs.charAt(0));
    }
    return opts;
}

/**
 * 提取数字集合
 * @param exp
 * @return
 */
private static List<Double> getNums(String exp) {
    //定义一个集合来存储数字
    List<Double> nums = new ArrayList<>();
    StringTokenizer sTokenizer = new StringTokenizer(exp, "+-*/");
    while (sTokenizer.hasMoreElements()) {
        String str = sTokenizer.nextElement().toString();
        //判断str中是否包含@,如果包含,则要将@符号转换成-。
        if (str.charAt(0) == '@') {
            //将@符号转换成-号
            str = "-" + str.substring(1);
        }
        //String要转换成Double类型
        double d = Double.parseDouble(str);
        nums.add(d);
    }
    return nums;
}

/**
 * 将负号转换成@符号
 * @param exp
 * @return
 */
private static String fu2At(String exp) {
    //先遍历字符串
    for (int i = 0; i < exp.length(); i++) {
        char c = exp.charAt(i);
        if (c == '-') {
            //如果c是第零个
            if (i == 0) {
                //一定表示负号
                exp = "@" + exp.substring(1);
            }else {
                //如果不是0的位置
                //判断c前面的一个字符是否是运算符
                char prev = exp.charAt(i - 1);
                if (prev == '+' || prev == '-' || prev == '*' || prev == '/') {
                    //说明c一定是表示负号
                    exp = exp.substring(0, i) + "@" + exp.substring(i + 1);
                }
            }
        }
    }
    return exp;
}

/*上述是基本小括号的运算,
下面2个方法是对中括号,大括号的增加*/

private static Double dkuohao(String exp) {
    int indexStart = exp.lastIndexOf('{');
    if(indexStart >= 0){
        int indexEnd = exp.indexOf('}',indexStart);
        String temp = exp.substring(indexStart+1,indexEnd);
        double d = zkuohao(temp);
        exp = exp.substring(0,indexStart)+d+exp.substring(indexEnd+1);
        return dkuohao(exp);
    }else{
        return zkuohao(exp);
    }
}

private static Double zkuohao(String exp) {
    int indexStart = exp.lastIndexOf('[');
    if(indexStart >= 0){
        int indexEnd = exp.indexOf(']',indexStart);
        String temp = exp.substring(indexStart+1,indexEnd);
        double d = calcKuohao(temp);
        exp = exp.substring(0,indexStart)+d+exp.substring(indexEnd+1);
        System.out.println(exp);
        return zkuohao(exp);
    }else{
        return calcKuohao(exp);
    }
}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值