解决double类型数据四则运算精度丢失问题

直接对double类型的数据进行计算,很容易发生精度丢失问题
在这里插入图片描述
使用BigDecimal类计算,可以避免精度丢失

 				//Double num2 = Double.parseDouble(numStack.pop());
                //Double num1 = Double.parseDouble(numStack.pop());
            	BigDecimal num2 = new BigDecimal(numStack.pop());
            	BigDecimal num1 = new BigDecimal(numStack.pop());
                if(arrays[i].equals("+")){
                    BigDecimal result = num1.add(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("-")){
                	BigDecimal result = num1.subtract(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("*")){
                	BigDecimal result = num1.multiply(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("/")){
                	BigDecimal result = num1.divide(num2);
                    numStack.push(result.toString());
                }

为了完成多个数据的组合运算,这里使用栈对运算符和运算数进行管理


设计一个存放字符串对象的栈类

public class Stack {
    private ArrayList<String> stack = new ArrayList<>();

    public boolean isEmpty(){
        return stack.size() == 0;
    }
    public int getSize(){
        return stack.size();
    }
    public String peek(){
        if(!isEmpty()) {
            return stack.get(stack.size() -1 );
        }
        else {
            return "false";
        }
    }
    public String pop(){
        if(!isEmpty()){
            String top = stack.get(stack.size() - 1);
            stack.remove(stack.size() - 1);
            return top;
        }
        else{
            return "false";
        }
    }
    public void push(String o){
        stack.add(o);
    }
    @Override
    public String toString(){
        return "Stack:" + stack.toString();
    }
}

计算类

public class Compute {
    public static void main(String[] args){
        Scanner input = new Scanner(System.in);
        String str = input.nextLine();

        String[] inOrderArrays = strToArrays(str);
        System.out.println(Arrays.toString(inOrderArrays));
        String[] postOrderArrays = toPostOrder(inOrderArrays);
        System.out.println(Arrays.toString(inOrderArrays));
        BigDecimal result = toCompute(postOrderArrays);
        System.out.println(result);
    }
    /*
    将字符串分割成操作数和操作符的字符串数组
    */
    public  static String[] strToArrays(String str){
        int strLength = str.length();
        int beginIndex = 0; int endIndex = 0;
        String[] Arrays = new String[strLength];
        int arraysIndex = 0;

        for(int i = 0; i < strLength; i++){
            if(str.charAt(i)=='*'||str.charAt(i)=='/'||str.charAt(i)=='+'||str.charAt(i)=='-'||str.charAt(i)=='('||str.charAt(i)==')'){
                endIndex = i -1 ;
                if(beginIndex <= endIndex ){
                    Arrays[arraysIndex] = str.substring(beginIndex, endIndex+1);
                    Arrays[arraysIndex + 1] = String.valueOf(str.charAt(i));
                    arraysIndex += 2;
                    beginIndex = i + 1;
                }
                else{
                    Arrays[arraysIndex] = String.valueOf(str.charAt(i));
                    arraysIndex += 1;
                    beginIndex = i + 1;
                }
            }
        }
        Arrays[arraysIndex] = str.substring(beginIndex, str.length());
        String[] Arrays2 = new String[arraysIndex+1];
        for(int i = 0; i < arraysIndex+1; i++) {
            Arrays2[i] = Arrays[i];
        }
        return Arrays2;
    }
    /*
    将中缀表达式转为后缀表达式,返回的是字符串数组
    */
    public static String[] toPostOrder(String[] arrays){
        /*规则:
        *1,运算数直接输出
        *2,左括号压入堆栈
        *3,右括号 将栈顶的运算符弹出并输出,括号出栈不输出
        *4,运算符:
        *    若优先级大于栈顶运算符,压入栈
        *    若优先级小于或等于栈顶运算符,栈顶运算符弹出并输出,
        *       继续和新栈顶比较,直到比栈顶运算符优先级大,将它压入栈
        *5,对象处理完毕后,将栈中运算符弹出并输出
        */
        Stack operStack = new Stack();//创建了一个操作符的栈
        int arraysLength = arrays.length;
        String[] arrays2 = new String[arraysLength];//输出后的字符数组
        int tempIndex = 0;

        //将字符串数组遍历
        for(int i = 0; i < arraysLength; i++){
            //操作符入栈
            if(isOper(arrays[i])){
                //栈为空时直接入栈
                if(operStack.isEmpty()){
                    operStack.push(arrays[i]);
                }
                else{
                    //操作符为"("时直接入栈
                    if( arrays[i].equals("(")  ){
                        operStack.push(arrays[i]);
                    }
                    //操作符为")"时栈顶出栈并输出,直到遇到"(", "("出栈,")"不入栈
                    else if( arrays[i].equals(")") ){
                        while(operStack.peek().equals("(") == false ){
                            arrays2[tempIndex] = operStack.pop();
                            tempIndex += 1;
                        }
                        operStack.pop();//"("出栈
                    }
                    //其他操作符需要比较与栈顶的优先级
                    else{
                        //栈顶是"(", 直接入栈
                        if(operStack.peek().equals("(") ){
                            operStack.push(arrays[i]);
                        }
                        else{
                            //优先级高,直接入栈
                            if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))
                                && operStack.isEmpty() == false ){
                                operStack.push(arrays[i]);
                            }
                            //优先级低或者相等,栈顶出栈并输出,直到优先级比栈顶高
                            else{
                                while(getPriority(arrays[i].charAt(0)) <= getPriority(operStack.peek().charAt(0))
                                        && operStack.isEmpty() == false){
                                    arrays2[tempIndex] = operStack.pop();
                                    tempIndex += 1;
                                    //若栈顶全部弹出,则直接入栈
                                    if(operStack.isEmpty()) {
                                        operStack.push(arrays[i]);
                                        break;
                                    }
                                }
                                if(getPriority(arrays[i].charAt(0)) > getPriority(operStack.peek().charAt(0))){
                                    operStack.push(arrays[i]);
                                }
                            }
                        }
                    }
                }
            }
            //操作数直接添加到 字符串数组2
            else if(isNum(arrays[i])){
                arrays2[tempIndex] = arrays[i];
                tempIndex += 1;
            }
            else{
            }
        }
        while(!operStack.isEmpty()){
            arrays2[tempIndex] = operStack.pop();
            tempIndex += 1;
        }
        String[] arrays3 = new String[tempIndex];
        for(int i = 0; i < tempIndex ;i++){
            arrays3[i] = arrays2[i];
        }
        return arrays3;
    }
    /*
    得到操作符的优先级
    */
    public static int getPriority(char c){
        if(c == '*' || c == '/'){
            return 2;
        }
        else if (c == '+' || c == '-'){
            return 1;
        }
        else{
            return 999;
        }
    }
    /*
    由后缀表达式计算得值
    */
    public static BigDecimal toCompute(String[] arrays){
        /*规则:
        *中缀表达式不用比较优先级
        *将运算数入栈,每读到一个运算符
        *就弹出栈顶的两个运算数,运算完毕后将结果压入栈
        */
        Stack numStack = new Stack();//创建了一个操作数的栈
        int arraysLength = arrays.length;
        //遍历后缀表达式的字符串数组
        for(int i = 0; i < arraysLength; i++){
            if(isNum(arrays[i])){
                numStack.push(arrays[i]);
            }
            else if(isOper(arrays[i])){
                //Double num2 = Double.parseDouble(numStack.pop());
                //Double num1 = Double.parseDouble(numStack.pop());
            	BigDecimal num2 = new BigDecimal(numStack.pop());
            	BigDecimal num1 = new BigDecimal(numStack.pop());
                if(arrays[i].equals("+")){
                    BigDecimal result = num1.add(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("-")){
                	BigDecimal result = num1.subtract(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("*")){
                	BigDecimal result = num1.multiply(num2);
                    numStack.push(result.toString());
                }
                else if(arrays[i].equals("/")){
                	BigDecimal result = num1.divide(num2);
                    numStack.push(result.toString());
                }
                else{
                }
            }
            else{
            }
        }
        //Double result = Double.parseDouble(numStack.pop());
        BigDecimal result = new BigDecimal(numStack.pop());
        return result;
    }
    /*
    判断该字符串是否为操作符
    */
    public static boolean isOper(String str){
        if(str.equals("*")||str.equals("/")||
            str.equals("+")||str.equals("-")||
            str.equals("(")||str.equals(")")){
                return true;
            }
        else{
            return false;
        }
    }
    /*
    判断该字符串是否为操作数
    */
    public static boolean isNum(String str){
        if(str.equals("*")||str.equals("/")||
            str.equals("+")||str.equals("-")||
            str.equals("(")||str.equals(")")){
                return false;
            }
        else{
            return true;
        }
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值