数据结构(四)java模拟计算器四则运算算法

用java模拟解决计算器四则运算算法问题.

/**
 * 模拟实现计算器算法功能
 */
public class Calc {

    public static void main(String[] args) {
        String exp = "-3*-(3+6/6-3)*1";
        System.out.println(calcBracket(exp));
    }

    /**
     * 带括弧的四则运算
     * @param exp 带括弧的表达式
     * @return
     */
    public static double calcBracket(String exp){
        //从最里面的括号开始运算,exp中最后出现的(最内层的括号
        int lastIndexOf = exp.lastIndexOf('(');
        //两种结果
        if (lastIndexOf != -1) {
            //有
            //1.计算最内层括号表达式的值,找对应的右括号
            int rightIndexOf = exp.indexOf(')', lastIndexOf);
            double d = calc(exp.substring(lastIndexOf+1,rightIndexOf));
            //2.把运算结果拼接
            exp = exp.substring(0, lastIndexOf)+d+exp.substring(rightIndexOf+1);
            return calcBracket(exp);
        }else {
            //没有
            //没有括号的表达式
            return calc(exp);
        }
    }

    /**
     * 
     * @param exp 不带括号的四则表达式
     * @return
     */
    public static double calc(String exp){
        //1.把表示负数的-号换成@号
        exp = fu2At(exp);
        //2.数字的分类
        List<Double> numbers = splitNumExp(exp);
        //3.运算符的分离
        List<Character> ops = splitOpfromExp(exp);
        //4.先乘除
        for (int i = 0; i < ops.size(); i++) {
            //判断,运算符是否是乘除
            char op = ops.get(i);
            //是,取出,运算
            if (op == '*' || op == '/') {
                //取出来,运算
                ops.remove(i);//后面的数据往前顺序移动
                //运算
                //从数字容器中取出对应运算符的两个数字
                double d1 = numbers.remove(i);
                double d2 = numbers.remove(i);

                if (op == '*') {
                    d1 *= d2;
                }else {
                    d1 /= d2;
                }

                //把运算结果放入数字容器中i的位置
                numbers.add(i, d1);//原来i位置(包括)后面的数据依次往后顺移
                i--;
            }
        }
        //5.后加减
        while (!ops.isEmpty() ) {
            char op = ops.remove(0);
            double d1 = numbers.remove(0);
            double d2 = numbers.remove(0);
            //运算
            if (op == '+') {
                d1 += d2;
            } else {
                d1 -= d2;
            }
            //把运算结果插入到数字容器中0的位置
            numbers.add(0, d1);
        }
        //6.容器中的第一个数据就是结果
        return numbers.get(0);
    }

    /**
     * 从表达式中分离表达式和运算符
     * @param exp
     * @return
     */
    private static List<Character> splitOpfromExp(String exp) {
        List<Character> ops = new ArrayList<>();
        StringTokenizer st = new StringTokenizer(exp, "1234567890.@");
        while (st.hasMoreTokens()) {
            char c = st.nextElement().toString().trim().charAt(0);
            ops.add(c);
        }
        return ops;
    }

    /**
     * 分离出数字
     * @param exp
     * @return
     */
    private static List<Double> splitNumExp(String exp) {
        List<Double> numbers = new ArrayList<>();
        StringTokenizer st = new StringTokenizer(exp, "+-*/");
        while (st.hasMoreTokens()) {
            String numStr = st.nextElement().toString().trim();
            if (numStr.charAt(0) == '@') {
                numStr = "-" + numStr.substring(1);
            }
            numbers.add(Double.parseDouble(numStr));
        }
        return numbers;
    }

    /**
     * 把-号换成@号
     * @param exp
     * @return
     */
    private static String fu2At(String exp) {
        for (int i = 0; i < exp.length(); i++) {
            char c = exp.charAt(i);
            if (c == '-') {
                //判断是否是负数
                if (i == 0) {
                    //第一个位置肯定是负数
                    exp = "@"+exp.substring(1);
                }else {
                    //不是第一个位置
                    //判断前一个位置是否是运算符
                    char cprev = exp.charAt(i - 1);
                    if (cprev == '+' || cprev == '-' || cprev == '*' || cprev == '/') {
                        exp = exp.substring(0, i)+"@"+exp.substring(i+1);
                    }
                }
            }
        }
        return exp;
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值