能实现优先级的计算器

我在网上看了很多的计算器都是那种没有实现优先级预算的,都是按照输入顺序来计算的,我不是很喜欢那种,然后我在网上查了查有没有别的办法,然后我知道逆波兰表达式,要实现优先级计算器,这个技能是要掌握的,有小伙伴感兴趣的话可以去网上查一查学一下,我在这就不多说,就简单的提一下

  • 举一个栗子:
    原表达式 :2*(4-1) // 这里暂时先不考虑中间的变化过程,待会再说
    逆波兰表达式 :2 4 1 - *
    首先我们要遍历你波兰表达式,遇到时数字的话我们先不管,当我们遇到第一个符号是 - 时让 - 号的前面两个数字进行相应的运算,然后就会得到一个新的值,再遍历遇到号,遇到号时让他的前面两位进行预算,是一开始的2 和刚才3在进行运算,这样就实现了优先级运算

1.我么首先要考虑的是怎么获得逆波兰表达式
这时我们要定义两个栈,一个用来存放数字,一个存放符号,那么我么就要对原来的基础的表达式进行拆分,肯定会有人想到调用一个现成方法然后直接拆分成字符,这样操作不是很好 例如: 12+13 会被拆分成 1,2,+,1,3 ,所以要换一种方法
2.其次就是要考虑符号的优先级

/*
将数字和符号分离开我的思路是,给符号两边加上一个任意的字符,然后变成一个新的字符串,然后通过刚才加的这个字符来截取,来把他们分开
*/
 function nbl(text){
        var operand = []; //用于存放操作数的栈
        var operator = []; //用于存放操作符的栈
        var textArr = text.split('');
        var newTextArr = [];

        for(var i = 0; i < textArr.length; i++){
      
            if(text[i] == "+"||text[i]== "-"||text[i]== "*"||text[i]== "/"||text[i]== "("||text[i]== ")" && text[i] != ".")   //这里可以优化一下,我这样写就是直观容易理解一点{
                newTextArr.push("|",text[i],"|");
            }
            else{
                newTextArr.push(textArr[i]);
            }
        }
        var calTextArr = newTextArr.join('').split("|");
        calTextArr.unshift("#")

        for(var i = 0; i < calTextArr.length; i++){
            //如果是数字则直接入栈
            if(Number(calTextArr[i]) || Number(calTextArr[i]) == 0){
                operand.push(calTextArr[i]);
            }
            //如果是操作符则再根据不同的情况进行操作
            else {
                switch(true){
                    //如果operator栈顶是“(”或者遍历到的操作符是“(”则直接入栈
                    case calTextArr[i] == "(" && operator.slice(-1)[0] == "(":
                        operator.push(calTextArr[i]);
                        break;
                    /*如果遍历到的操作符是“)”则把operator中的操作符依次弹出并压入
                    operand中直至operator栈顶操作符为“(”,然后将“(”也弹出,但不压入
                    operand栈中
                    */
                    //(4+5)*2*4/2+3
                    case calTextArr[i] == ")":
                        do{
                            operand.push(operator.pop());
                        }while(operator.slice(-1)[0] != "(");
                        operator.pop();
                        break;

                    //如果是其他的操作符,则比较优先级后再进行操作
                    default:
                        if(operator.length == 0){
                            operator.push(calTextArr[i]);
                        }
                        else if(compareOperator(calTextArr[i],operator.slice(-1)[0])){
                            do{
                                operand.push(operator.pop());
                                var compareResult = compareOperator(calTextArr[i],operator.slice(-1)[0]);
                            }while(compareResult);
                            operator.push(calTextArr[i]);
                        }
                        else {
                            operator.push(calTextArr[i]);
                        }
                        break;
                }
            }
        }
        //遍历结束后,将operator中的元素全部压入operand中
        operator.forEach(function(){
            operand.push(operator.pop());
        });
        //在把用于比较的“#”字符去掉
        operator.pop();
        var nearr = new Array();
        for(var i = 0,j = 0;i < operand.length;i++){
            if(operand[i] != ""){
                nearr[j] = operand[i];
                j++;
            }
        }
    
        return nearr;
    }


//--------------------------下面的代码是比较符号优先级的方法

function compareOperator(a,b){
        var aLevel = getOperatorRand(a),
            bLevel = getOperatorRand(b);

        if(aLevel <= bLevel){
            return true;
        }
        else if(aLevel > bLevel){
            return false;
        }
    }

    //比较操作符的优先级

    function getOperatorRand(operator){
        switch(operator){
            case "#":
                return 0;
            case "-":
                return 1;
                break;
            case "+":
                return 1;
                break;
            case "*":
                return 2;
                break;
            case "/":
                return 2;
                break;
        }
    }

拿到逆波兰表达式之后我们接下来就是运算

 function jieguo(RPNarr){
        var result;
        while(RPNarr.length > 1)
            RPNarr =  singleResult(RPNarr);
        console.log(RPNarr)
        result = RPNarr[0];
        return result;
    }


    //每遇到一个操作符就进行一次运算然后更新数组,直到算出最终结果。
    function singleResult(RPNarr){
        for(var i = 0,max = RPNarr.length; i < max; i++){
            console.log(!Number(RPNarr))
            if(!Number(RPNarr[i])){
                switch(RPNarr[i]){
                    case "+":
                        var addResult = Number(RPNarr[i-2]) + Number(RPNarr[i-1]);
                        RPNarr.splice(i-2,3,addResult);
                        return RPNarr;
                        break;
                    case "-":
                        var addResult = Number(RPNarr[i-2]) - Number(RPNarr[i-1]);
                        RPNarr.splice(i-2,3,addResult);
                        return RPNarr;
                        break;
                    case "*":
                        var addResult = Number(RPNarr[i-2]) * Number(RPNarr[i-1]);
                        RPNarr.splice(i-2,3,addResult)
                        return RPNarr;
                        break;
                    case "/":
                        var addResult = Number(RPNarr[i-2]) / Number(RPNarr[i-1]);
                        RPNarr.splice(i-2,3,addResult)
                        return RPNarr;
                        break;
                }
            }
        }
    }

核心内容已经完成了接下来就是一些点击事件和html的简单样式

//--------这里是一些按钮的js代码,没什么说的


   //获取显示框
    var show_result = document.getElementById("show");
    var show_result1 = document.getElementById("show1");
    //获取清除键
    var clear_btn = document.getElementById("clear");
    //获取退格键
    var del_btn = document.getElementById("del");
    //获取等号
    var result_btn = document.getElementById("result");
    //获取所有的数字键
    var nums = document.getElementsByClassName("num");
    //获取所有的操作符键
    var czfs = document.getElementsByClassName("czf");
    //获取小数点
    var dian = document.getElementById("dian");

    //定义两个变量来进行存储
    var numValue1 = '';
    var numValue2 = '';


    for(var i = 0;i < nums.length;i++){
        nums[i].onclick = function () {
                numValue1 +=  this.innerText;
                numValue2 += this.innerText;
                show_result.value = numValue2;


        }
    }


    for (var j = 0;j < czfs.length;j++){
        czfs[j].onclick = function () {
            numValue1 = "";
            numValue2 += this.innerText;
            show_result.value = numValue2;
        }

    }


    //退格按键
    del_btn.onclick = function() {
        var i = numValue2.length-1;
        var j = numValue1.length-1;
       // var nu = numValue1.charAt(i) ;           //获取要删除的元素进行判断

        if(i >= 1){
            numValue2 = numValue2.substring(0,i);
        }else  {
            numValue2 = "";
        }

        if(j >= 1){
            numValue1 = numValue1.substring(0,i);
        }else  {
            numValue1 = "";
        }

        if(numValue2.length == 0){
            show_result.value = 0;
        }else {
            show_result.value = numValue2;
        }

    }

    function Dian() {

       if(numValue1.indexOf(".") == -1){
           if(numValue2.length == 0 ){
               numValue1 = "0.";
               numValue2 = "0.";
           }else {
               numValue1 += ".";
               numValue2 +=".";
           }

           show_result.value = numValue2;
       }
    }

    //清除全部
    clear_btn.onclick =function () {
        numValue1 = "";
        numValue2 = "";
        show_result.value = "0";
        show_result1.value = "0";
    }



    result_btn.onclick = function () {
         var s = nbl(numValue2);
         var maxnum = jieguo(s).toFixed(5)*1;
        show_result.value = maxnum;
        show_result1.value = numValue2;
        numValue2 = maxnum;
        numValue1 = "";

    }

最后就是huml和css
// 样式比较丑,别喷,你们可以自己设置设置弄好看一点




    
    Title
    


  

C ( ) /
7 8 9 *
4 5 6 -
1 2 3 +
0 退格 . =

你可能感兴趣的:(能实现优先级的计算器)