文字计算器 对输入的加减乘除等四则运算得出结果,是否考虑负数,小数等(难度:★★★★)由自己决定

题目一:考察分析处理问题能力(难度:★★★)
    文字计算器
    对输入的加减乘除等四则运算得出结果,是否考虑负数,小数等(难度:★★★★)由自己决定
例如:输入:1+2*2-4  输出为1  
     输入:1+2+3+4 输出为10
     输入:1+2/5-4*2 输出为-6.6
    

在做这个题的时候,也看到网上有很多关于这个四则运算的算法实现。但是我还是想自己思考一下。我的想法其实很直接。分析思路如下:

1、四则运算优先级: 乘 除 加 减

2、按照优先级将输入的字符串进行划分计算

(1)第一优先级的乘法先通过字符串进行切分,分别获取*号前面部分和后面部分。然后进行计算。最近将计算结果6替换2*3的位置、8替换4*2的位置。

(2)第二优先级除法,也按照第一优先级的方式进行计算和字符串拼接。

(3)第三优先级加法,也按照第一优先级的方式进行计算和字符串拼接。

(4)第四优先级减法,也按照第一优先级的方式进行计算和字符串拼接。

经过四次运算,也就算成了整个计算。如果有扩展功能,比如添加大括号什么的,只是添加一层皮,多一层包装而已。真正的计算为:1、获取具体优先级表达式。2、计算。3、替换位置,形成子字符串。

具体实现代码如下:

package com.yxie.test.arithmetic;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.yxie.test.arithmetic.constant.ArithmeticEnum;
import com.yxie.test.arithmetic.pojo.ReplaceArithmeticPojo;
import com.yxie.test.arithmetic.util.ArithmeticUtil;

public class ArithmeticTest {

    private static final Integer      PRECISION    = 20;
    private static final RoundingMode ROUNDINGMODE = RoundingMode.HALF_UP;

    /***
     * 获取计算前面部分的数字
     *
     * @return
     */
    public Map<Integer, String> getPreIndexStr(String subArithmeticStr) {
        Map<Integer, String> numIndexMap = new HashMap<Integer, String>();
        Integer tempIndex = 0;
        StringBuffer tempSb = new StringBuffer();
        for (int i = subArithmeticStr.length() - 1; i >= 0; i--) {
            if (ArithmeticEnum.MULTIPLICATION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.DIVISION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.ADD.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.REDUCE.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else {
                tempSb.insert(0, subArithmeticStr.charAt(i));// 前面拼接
            }
        }
        numIndexMap.put(tempIndex, tempSb.toString());
        return numIndexMap;
    }

    /***
     * 获取计算后面部分最近的数字
     *
     * @return
     */
    public Map<Integer, String> getAfterIndexStr(String subArithmeticStr) {
        Map<Integer, String> numIndexMap = new HashMap<Integer, String>();
        Integer tempIndex = 0;
        StringBuffer tempSb = new StringBuffer();
        for (int i = 0; i < subArithmeticStr.length(); i++) {
            if (ArithmeticEnum.MULTIPLICATION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.DIVISION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.ADD.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else if (ArithmeticEnum.REDUCE.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                tempIndex = i;
                break;
            } else {
                tempSb.append(subArithmeticStr.charAt(i));
            }
        }
        numIndexMap.put(tempIndex, tempSb.toString());
        return numIndexMap;
    }

    /**
     * 按精确度计算结果
     *
     * @param numString
     * @param precision
     * @param roundingMode
     * @return
     */
    public static BigDecimal getBigDecimal(String numString, int precision, RoundingMode roundingMode) {
        String precisionFlag = "0";
        if (numString == null || numString.equals("")) {
            precisionFlag = "0.00";
        } else {
            precisionFlag = numString;
        }
        BigDecimal bigDecimal = new BigDecimal(precisionFlag);
        bigDecimal.setScale(precision, roundingMode);
        return bigDecimal;
    }

    public StringBuffer calculateVal(StringBuffer inputArithmeticStr, String arithmeticEnumVal) {
        List<ReplaceArithmeticPojo> repList = new ArrayList<ReplaceArithmeticPojo>();
        ReplaceArithmeticPojo tempRepl = null;
        boolean addTempReplBool = false;
        for (int i = 0; i < inputArithmeticStr.length(); i++) {
            if (arithmeticEnumVal.equals(Character.toString(inputArithmeticStr.charAt(i)))) {
                // System.out.println("in:" + i);
                Map<Integer, String> preNumIndexMap = getPreIndexStr(inputArithmeticStr.substring(0, i));// 前面部分
                Integer preStrIndex = (Integer) preNumIndexMap.keySet().iterator().next();
                String preStr = (String) preNumIndexMap.get(preStrIndex);
                Map<Integer, String> afterNumIndexMap = getAfterIndexStr(inputArithmeticStr.substring(i + 1,
                                                                                                      inputArithmeticStr.length()));// 后面部分
                Integer afterStrIndex = (Integer) afterNumIndexMap.keySet().iterator().next();
                String afterStr = (String) afterNumIndexMap.get(afterStrIndex);
                // 判断传入参数是否慢主条件
                if (arithmeticEnumVal.equals(ArithmeticEnum.DIVISION.getValue())) {
                    if (!ArithmeticUtil.isDouble(preStr) || !ArithmeticUtil.isNumber(afterStr)) {
                        return new StringBuffer().append("ERROR:" + preStr + ";" + afterStr);
                    }
                } else if (!ArithmeticUtil.isDouble(preStr) || !ArithmeticUtil.isDouble(afterStr)) {
                    return new StringBuffer().append("ERROR:" + preStr + ";" + afterStr);
                }
                if (preStrIndex != 0) {
                    preStrIndex = preStrIndex + 1;
                }
                if (afterStrIndex == 0) {
                    afterStrIndex = inputArithmeticStr.length();
                } else {
                    afterStrIndex = i + 1 + afterStrIndex;

                }
                BigDecimal tempNumber = null;
                if (tempRepl != null) {
                    ReplaceArithmeticPojo addRepl = new ReplaceArithmeticPojo();
                    if (tempRepl.getEndIndex() >= preStrIndex) {// 开始时间和上一个tempRepl.getStartIndex()存在交集,也就是连续的计算如:2*4*5
                        tempNumber = calBigDecimal(arithmeticEnumVal, tempRepl.getCalVal(), afterStr);
                        addRepl.setCalVal(tempNumber.toString());
                        addRepl.setStartIndex(tempRepl.getStartIndex());
                        addRepl.setEndIndex(afterStrIndex);

                        tempRepl = addRepl;
                        addTempReplBool = true;
                    } else {
                        tempNumber = calBigDecimal(arithmeticEnumVal, preStr, afterStr);
                        if (addTempReplBool) {
                            repList.add(tempRepl);
                            tempRepl = null;
                            addTempReplBool = false;
                        }
                        addRepl.setCalVal(tempNumber.toString());
                        addRepl.setStartIndex(preStrIndex);
                        addRepl.setEndIndex(afterStrIndex);
                        tempRepl = addRepl;
                        addTempReplBool = true;
                    }

                } else {// 第一次
                    tempNumber = calBigDecimal(arithmeticEnumVal, preStr, afterStr);
                    tempRepl = new ReplaceArithmeticPojo();
                    tempRepl.setCalVal(tempNumber.toString());
                    tempRepl.setStartIndex(preStrIndex);
                    tempRepl.setEndIndex(afterStrIndex);
                    addTempReplBool = true;
                }

                // System.out.println("preStr:" + preStr + ";afterStr:" + afterStr);
                // System.out.println("preStrIndex:" + preStrIndex + ";afterStrIndex:" + afterStrIndex);
                // System.out.println("preSubString:" + inputArithmeticStr.substring(preStrIndex, afterStrIndex));
            }
        }

        if (addTempReplBool) {
            repList.add(tempRepl);
        }
        // System.out.println("======================begin repList==================");
        // for (int j = 0; j < repList.size(); j++) {
        // ReplaceArithmeticPojo eveRepPojo = repList.get(j);
        // System.out.println("getCalVal:" + eveRepPojo.getCalVal() + ";getStartIndex:" + eveRepPojo.getStartIndex()
        // + ";getEndIndex:" + eveRepPojo.getEndIndex());
        // }
        // System.out.println("======================end repList==================");
        // 开始进行替换
        StringBuffer replaceReturnSB = new StringBuffer();
        int tempEndIndex = -1;
        for (int j = 0; j < repList.size(); j++) {
            ReplaceArithmeticPojo eveRepPojo = repList.get(j);
            if (j == 0) {
                replaceReturnSB.append(inputArithmeticStr.substring(0, eveRepPojo.getStartIndex())).append(eveRepPojo.getCalVal());
                tempEndIndex = eveRepPojo.getEndIndex();
            } else {
                replaceReturnSB.append(inputArithmeticStr.substring(tempEndIndex, eveRepPojo.getStartIndex())).append(eveRepPojo.getCalVal());
                tempEndIndex = eveRepPojo.getEndIndex();
            }

            if (j == repList.size() - 1) {
                replaceReturnSB.append(inputArithmeticStr.substring(eveRepPojo.getEndIndex(),
                                                                    inputArithmeticStr.length()));
            }
        }
        return replaceReturnSB;
    }

    private BigDecimal calBigDecimal(String arithmeticEnumVal, String preStr, String afterStr) {
        BigDecimal preBigDecimal = getBigDecimal(preStr, PRECISION, ROUNDINGMODE);

        BigDecimal afterBigDecimal = getBigDecimal(afterStr, PRECISION, ROUNDINGMODE);
        BigDecimal tempNumber = getBigDecimal("", PRECISION, ROUNDINGMODE);
        if (arithmeticEnumVal.equals(ArithmeticEnum.ADD.getValue())) {
            tempNumber = preBigDecimal.add(afterBigDecimal);
        } else if (arithmeticEnumVal.equals(ArithmeticEnum.REDUCE.getValue())) {
            tempNumber = preBigDecimal.subtract(afterBigDecimal);
        } else if (arithmeticEnumVal.equals(ArithmeticEnum.MULTIPLICATION.getValue())) {
            tempNumber = preBigDecimal.multiply(afterBigDecimal);
        } else if (arithmeticEnumVal.equals(ArithmeticEnum.DIVISION.getValue())) {
            tempNumber = preBigDecimal.divide(afterBigDecimal, PRECISION, ROUNDINGMODE);
        }
        return tempNumber;
    }

    private void arithmetic(StringBuffer inputArithmeticStr) {
        StringBuffer sbBak = new StringBuffer();
        sbBak.append(inputArithmeticStr);// 用于备份提示信息用。
        // 存在乘法
        if (inputArithmeticStr.indexOf(ArithmeticEnum.MULTIPLICATION.getValue()) != -1) {
            inputArithmeticStr = calculateVal(inputArithmeticStr, ArithmeticEnum.MULTIPLICATION.getValue());
            if (inputArithmeticStr.toString().indexOf("ERROR") != -1) {
                System.out.println("输入的表达式(" + sbBak + ")有问题:" + inputArithmeticStr);
                System.exit(0);
            }
            // System.out.println("MULTIPLICATION inputArithmeticStr:" + inputArithmeticStr);
            // System.out.println("MULTIPLICATION:" + indexList);
        }

        // 存在除法
        if (inputArithmeticStr.indexOf(ArithmeticEnum.DIVISION.getValue()) != -1) {
            inputArithmeticStr = calculateVal(inputArithmeticStr, ArithmeticEnum.DIVISION.getValue());
            if (inputArithmeticStr.toString().indexOf("ERROR") != -1) {
                System.out.println("输入的表达式(" + sbBak + ")有问题:" + inputArithmeticStr);
                System.exit(0);
            }
            // System.out.println("DIVISION inputArithmeticStr:" + inputArithmeticStr);
            // System.out.println("DIVISION");
        }

        // 存在加法
        if (inputArithmeticStr.indexOf(ArithmeticEnum.ADD.getValue()) != -1) {
            inputArithmeticStr = calculateVal(inputArithmeticStr, ArithmeticEnum.ADD.getValue());
            if (inputArithmeticStr.toString().indexOf("ERROR") != -1) {
                System.out.println("输入的表达式(" + sbBak + ")有问题:" + inputArithmeticStr);
                System.exit(0);
            }
            // System.out.println("ADD inputArithmeticStr:" + inputArithmeticStr);
            // System.out.println("ADD");
        }

        // 存在减法
        if (inputArithmeticStr.indexOf(ArithmeticEnum.REDUCE.getValue()) != -1) {
            inputArithmeticStr = calculateVal(inputArithmeticStr, ArithmeticEnum.REDUCE.getValue());
            if (inputArithmeticStr.toString().indexOf("ERROR") != -1) {
                System.out.println("输入的表达式(" + sbBak + ")有问题:" + inputArithmeticStr);
                System.exit(0);
            }
            // System.out.println("REDUCE inputArithmeticStr:" + inputArithmeticStr);
            // System.out.println("REDUCE");
        }
        System.out.println("======================begin 执行结果===================================");
        System.out.println(inputArithmeticStr);
        System.out.println("======================end 执行结果===================================");
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        // 1/3/2+4/3+45/2+2*2*2/2*2*2*2*2*2*2*2*2*2+1/3/2+4/3+45/2+2*2*2*2*2*2*2*2*2*2*2*2*2
        StringBuffer inputArithmeticStr = new StringBuffer().append("1/3/2+4/3-45/2+2*2*2/2*2*2*2*2*2*2*2*2*2");
        System.out.println("inputArithmeticStr:" + inputArithmeticStr);
        ArithmeticTest arithmeticTest1 = new ArithmeticTest();
        arithmeticTest1.arithmetic(inputArithmeticStr);
    }

}

package com.yxie.test.arithmetic.pojo;

public class ReplaceArithmeticPojo {

    private Integer startIndex;
    private Integer endIndex;
    private String  calVal;

    public Integer getStartIndex() {
        return startIndex;
    }

    public void setStartIndex(Integer startIndex) {
        this.startIndex = startIndex;
    }

    public Integer getEndIndex() {
        return endIndex;
    }

    public void setEndIndex(Integer endIndex) {
        this.endIndex = endIndex;
    }

    public String getCalVal() {
        return calVal;
    }

    public void setCalVal(String calVal) {
        this.calVal = calVal;
    }

}


package com.yxie.test.arithmetic.util;

import java.math.BigDecimal;

public class ArithmeticUtil {

    /***
     * 只能是正整数
     *
     * @param str
     * @return
     */
    public static boolean isNumber(String str) {
        return str.matches("\\d+");
    }

    /***
     * 判断是否慢主数字的条件。包括整数,负数,double类型。
     *
     * @param str
     * @return
     */
    public static boolean isDouble(String str) {
        return str.matches("-?\\d+\\.?\\d*");
    }

    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double addReturnDouble(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.add(decimal2).doubleValue();
    }

    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static int addReturnInt(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.add(decimal2).intValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static double subReturnDouble(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.subtract(decimal2).doubleValue();
    }

    /**
     * 提供精确的减法运算。
     *
     * @param v1 被减数
     * @param v2 减数
     * @return 两个参数的差
     */
    public static int subReturnInt(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.subtract(decimal2).intValue();
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static double mulReturnDouble(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.multiply(decimal2).doubleValue();
    }

    /**
     * 提供精确的乘法运算。
     *
     * @param v1 被乘数
     * @param v2 乘数
     * @return 两个参数的积
     */
    public static int mulReturnInt(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.multiply(decimal2).intValue();
    }

    /**
     * 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到 小数点以后10位,以后的数字四舍五入。
     *
     * @param v1 被除数
     * @param v2 除数
     * @return 两个参数的商
     */
    public static double devReturnDouble(String v1, String v2) {
        BigDecimal decimal1 = new BigDecimal(v1);
        BigDecimal decimal2 = new BigDecimal(v2);
        return decimal1.divide(decimal2, 60, BigDecimal.ROUND_HALF_UP).doubleValue();// 保证大数据不报错
    }
}

//单元测试的类

package com.yxie.test.arithmetic;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.junit.Test;

import com.yxie.test.arithmetic.constant.ArithmeticEnum;
import com.yxie.test.arithmetic.pojo.ReplaceArithmeticPojo;
import com.yxie.test.arithmetic.util.ArithmeticUtil;

public class ArithmeticJunit {

    @Test
    public void testIndexFlag() {
        String subArithmeticStr = "1+233.5";
        StringBuffer tempSb = new StringBuffer();
        for (int i = subArithmeticStr.length() - 1; i > 0; i--) {
            if (ArithmeticEnum.MULTIPLICATION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.DIVISION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.ADD.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.REDUCE.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else {
                tempSb.insert(0, subArithmeticStr.charAt(i));
            }
        }
        System.out.println("tempSb:" + tempSb);

    }

    @Test
    public void testIsNumber() {
        System.out.println("23".matches("\\d+"));
        System.out.println("2311111111".matches("\\d+"));
        System.out.println("23".matches("-?\\d+\\d*"));
        System.out.println("-23.34".matches("-?\\d+\\d*"));
    }

    @Test
    public void testIsDouble() {
        System.out.println("-23".matches("-?\\d+\\.?\\d*"));
        System.out.println("23".matches("-?\\d+\\.?\\d*"));
        System.out.println("-23.34".matches("-?\\d+\\.?\\d*"));
    }

    @Test
    public void testBigDecimal() {
        BigDecimal realCJCommi1 = new BigDecimal("-34");
        BigDecimal realCJCommi2 = new BigDecimal("-34");
        System.out.println(realCJCommi1.add(realCJCommi2));
        System.out.println(-34 + (-34));
        System.out.println(add(-34, -34));
    }

    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    @Test
    public void testList() {
        List<ReplaceArithmeticPojo> repList = new ArrayList<ReplaceArithmeticPojo>();
        ReplaceArithmeticPojo tempRepl = new ReplaceArithmeticPojo();
        tempRepl.setCalVal("23");
        repList.add(tempRepl);
        tempRepl = null;
        for (ReplaceArithmeticPojo rep : repList) {
            System.out.println(rep.getCalVal());
        }
    }

    /***
     * 获取计算后面部分最近的数字
     *
     * @return
     */
    @Test
    public void testGetAfterIndexStr() {
        String subArithmeticStr = "2.121+233.5";
        StringBuffer tempSb = new StringBuffer();
        for (int i = 0; i < subArithmeticStr.length(); i++) {
            if (ArithmeticEnum.MULTIPLICATION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.DIVISION.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.ADD.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else if (ArithmeticEnum.REDUCE.getValue().equals(Character.toString(subArithmeticStr.charAt(i)))) {
                break;
            } else {
                tempSb.append(subArithmeticStr.charAt(i));
            }
        }
        System.out.println("tempSb:" + tempSb);
    }

    @Test
    public void test() {
        StringBuffer a = new StringBuffer("aaaa");
        a.insert(0, "bb");
        System.out.println(a);
    }

    @Test
    public void testBigDecimalArithmeticUtil() {
        System.out.println(ArithmeticUtil.addReturnDouble("-1.4", "3"));
        System.out.println(ArithmeticUtil.addReturnDouble("1.4", "3"));
        System.out.println(ArithmeticUtil.addReturnDouble("3.4444", "3"));
        System.out.println(ArithmeticUtil.addReturnInt("3", "3"));
        System.out.println(ArithmeticUtil.subReturnDouble("3", "3"));
        System.out.println(ArithmeticUtil.subReturnInt("3", "3"));
        System.out.println(ArithmeticUtil.mulReturnDouble("3", "3"));
        System.out.println(ArithmeticUtil.mulReturnInt("3", "3"));
        System.out.println("devReturnDouble:" + ArithmeticUtil.devReturnDouble("3", "3.34433434343443343434"));
    }

    public static void main(String[] args) {
        System.out.println("0.8970394978269958370069547891983".length());
    }
}

具体网上实现自己去搜吧,很多,呵呵呵。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值