HTML计算器 逆波兰表达式

由于课程js的需要 需要我们完成一个手敲的计算器 由于不准使用js中内置计算函数 所以只能自己敲 考虑算法 选择后缀表达式 也称为 逆波兰表达式 

如果你不懂逆波兰表达式是什么没关系 举个例子

1.C-A*B = CAB*-

2.A*(B+C) -D = ABC+*D-

3.-A+B-C+D = A-B+C-D+

4.6+(8-2) * 2/3 = 682-2*3/+

其实你就可以观察到先运算的符号永远在后运算符号的后面 这也是我们实现其运算的关键思路

先提供计算器的基本样式代码


</html><!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>计算器</title>
  <link rel="stylesheet" href="mian.css">
</head>
<body>
    <div class="container">
        <div class="calculator dark">
            <label class="switch">
                <input type="checkbox" id="theme-toggle">
                <span class="slider"></span>
            </label>
            <div class="display-screen">
                <div id="display"></div>
            </div>
            <div class="buttons">
                <table>
                    <tr>
                        <td><button class="btn-operator" id="clear">C</button></td>
                        <td><button class="btn-operator" id="/">&divide;</button></td>
                        <td><button class="btn-operator" id="*">&times;</button></td>
                        <td><button class="btn-operator" id="backspace"><</button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="7">7</button></td>
                        <td><button class="btn-number" id="8">8</button></td>
                        <td><button class="btn-number" id="9">9</button></td>
                        <td><button class="btn-operator" id="-">-</button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="4">4</button></td>
                        <td><button class="btn-number" id="5">5</button></td>
                        <td><button class="btn-number" id="6">6</button></td>
                        <td><button class="btn-operator" id="+">+</button></td>
                    </tr>
                    <tr>
                        <td><button class="btn-number" id="1">1</button></td>
                        <td><button class="btn-number" id="2">2</button></td>
                        <td><button class="btn-number" id="3">3</button></td>
                        <td><button class="btn-number" id=".">.</button></td>
                      
                    </tr>
                    <tr>
                        <td><button class="btn-operator" id="(">(</button></td>
                        <td><button class="btn-number" id="0">0</button></td>
                        <td><button class="btn-operator" id=")">)</button></td>
                        <td ><button class="btn-equal" id="equal">=</button></td>
                    </tr>
                    
                </table>
            </div>
        </div>
    </div>
    <script src="main.js">




    </script>
</body>
</html>

接下来使CSS代码

*{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    outline: 0;
    transition: all 0.5s ease;
}
body{
    font-family: sans-serif;
}
a{
    text-decoration: none;
    color: #fff;
}
body{
    background: #272343;
}
.container111{
    height: 100vh;
    width: 100vw;
    display: grid;
    place-items: center;
margin:  -250px auto;
margin-left: -150px;
}
.calculator{
    position: relative;
    margin:6% auto;
    height: auto;
    width: 23%;
    padding: 20px;
    border-radius: 10px;
    box-shadow: 0 0 30px #000;
}
/* The switch - the box around the slider */
.switch {
    font-size: 17px;
    position: relative;
    display: inline-block;
    width: 3.5em;
    height: 2em;
    position: absolute;
    top: 30px;
    right: 30px;
    color: #fff;
    cursor: pointer;
    z-index: 1;
  }
  
  /* Hide default HTML checkbox */
  .switch input {
    opacity: 0;
    width: 0;
    height: 0;
  }
  
  /* The slider */
  .slider {
    --background: #28096b;
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: var(--background);
    transition: .5s;
    border-radius: 30px;
  }
  
  .slider:before {
    position: absolute;
    content: "";
    height: 1.4em;
    width: 1.4em;
    border-radius: 50%;
    left: 10%;
    bottom: 15%;
    box-shadow: inset 8px -4px 0px 0px #fff000;
    background: var(--background);
    transition: .5s;
  }
  
  input:checked + .slider {
    background-color: #522ba7;
  }
  
  input:checked + .slider:before {
    transform: translateX(100%);
    box-shadow: inset 15px -4px 0px 15px #fff000;
  }

  .butbox button{
    margin-top: 10px;
    cursor: pointer;
    border: none;
    color: white;
    background-color: rgb(112,101,254);
    border-radius: 20px;
    width: 100px;
    height: 40px;
}


.butbox span{
    margin-top: 10px;
    cursor: pointer;
    border: none;
    color: white;
    background-color: rgb(112,101,254);
    border-radius: 20px;
    width: 100px;
    height: 40px;
}

#display{
    margin: 0 10px;
    height: 150px;
    width: auto;
    max-width: 270px;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    font-size: 30px;
    overflow-x: scroll;
}
#display::-webkit-scrollbar{
    display: block;
    height: 3px;
}
button{
    height: 60px;
    width: 60px;
    border: 0;
    border-radius: 30px;
    margin: 5px;
    font-size: 20px;
    cursor: pointer;
    transition: all 200ms ease;
}



button:hover{
    transform: scale(1.1);
}

/* 白天主题 */
.calculator{
    background-color: #fff;
}
.calculator #display{
    color: #0a1e23;
}
.calculator button#clear{
    background-color: #ffd5d8;
    color: #fc4552;
}
.calculator button.btn-number{
    background-color: #c3eaff;
    color: #000;
}
.calculator button.btn-operator{
    background-color: #ffd803;
    color: #f967f3;
}
.calculator button.btn-equal{
    background-color: #adf9e7;
    color: #000;
}

/* 夜间主题 */
.calculator.dark{
    background-color: #071115;
}
.calculator.dark #display{
    color: #f8fafd;
}
.calculator.dark button#clear{
    background-color: #2d191e;
    color: #bd3740;
}
.calculator.dark button.btn-number{
    background-color: #1b2f38;
    color: #f8fafb;
}
.calculator.dark button.btn-operator{
    background-color: #2e1f39;
    color: #aa00a4;
}
.calculator.dark button.btn-equal{
    background-color: #223323;
    color: #fff;
}

现在说一下算法的思想 

从左往右扫描逆波兰表达式  遇数字入栈;遇到运算符号,将栈中最上方的两个元素依次出栈并用运算符计算,将计算结果压入栈中。反复此过程

这样子讲可能有点抽象 举个例子

拿6+(8-2) * 2/3 = 682-2*3/+做实例

首先

682入栈 而后扫描到了-号 于是8-2为6 栈里就变成了66 而后继续扫描 到2 为662 扫描到了* 于是

6*2为12 栈就变成了6 12 依次类推

按步数来看

1. 6 8 2

2.6 6

3.6 12

4.6 4

5.10

这样子

最后栈里只剩下了10

接下来 详解一下我们js的关键函数

function fix(main) {
    var output = [];
    var stack = [];

    for (var i = 0; i < main.length; i++) {
        var taken = main[i];
        if (!isNaN(taken)) {
            var number = "";

            while (!isNaN(taken) || taken === '.') {
                number += taken;
                i++;
                taken = main[i];
            }
            output.push(number);
            i--;
        } else if (taken === '(') {
            stack.push(taken);
        } else if (taken === ")") {
            while (stack.length > 0 && stack[stack.length - 1] !== '(') {
                output.push(stack.pop());
            }
            stack.pop(); 
        } else {
            while (stack.length > 0 && fuhao(stack[stack.length - 1]) >= fuhao(taken)) {
                output.push(stack.pop());
            }
            stack.push(taken);
        }
    }
    while (stack.length > 0) {
        output.push(stack.pop());
    }
    console.log(output);
    return output;
}

主要就是这一段函数的作用 用来把我们的中缀表达式换成为后缀表达式

  1. 首先,定义两个数组变量 output 和 stack,output 数组用于存储转换后的后缀表达式,stack 数组用于存储运算符。

  2. 然后,通过 for 循环遍历输入的 main 中缀表达式数组中的每一个元素。

  3. 判断当前元素是否为数字,如果是,则表示为一个完整的数字,需要将连续的数字字符组合成一个完整的数字,并将其 push 到 output 数组中。使用 while 循环可以多次执行并将数字字符拼接成完整的数字。

  4. 如果当前元素是左括号 "(", 则将其直接 push 到 stack 数组中。

  5. 如果当前元素是右括号 ")", 则需要将 stack 数组中的运算符 pop 出来,直到遇到左括号 "(",并将这些运算符 push 到 output 数组中。注意,最后还需要将左括号 "(" 从 stack 数组中 pop 出来。

  6. 如果当前元素是运算符,则需要将 stack 数组中优先级比当前运算符高的运算符 pop 出来,并将这些运算符 push 到 output 数组中,然后将当前运算符 push 到 stack 数组中。

  7. 循环结束后,如果 stack 数组中还有运算符,则需要将这些运算符 pop 出来,并将其 push 到 output 数组中。

  8. 最后,返回 output 数组,即为转换后的后缀表达式。

如果还是有点没听懂没关系 接下来举个例子 希望能帮助你更好的去理解这段代码

给定中缀表达式:5*(54+56)/6

  1. 初始化 output = [] 和 stack = []
  2. 遍历中缀表达式 main:
    • 第一个字符是 5,将其转换为字符串并添加到 output 中,output = ["5"]
    • 下一个字符是 ,将其压入 stack 数组中,stack = [""]
    • 下一个字符是 (,将其压入 stack 数组中,stack = ["*", "("]
    • 下一个字符是 54,将其转换为字符串并添加到 output 中,output = ["5", "54"]
    • 下一个字符是 +,其优先级大于栈顶运算符 * 的优先级,将其压入 stack 数组中,stack = ["*", "(", "+"]
    • 下一个字符是 56,将其转换为字符串并添加到 output 中,output = ["5", "54", "56"]
    • 下一个字符是 ),弹出栈顶元素 + 并添加到 output 中,output = ["5", "54", "56", "+"] 继续弹出栈顶元素 (,将后面的运算符添加到 output 中,output = ["5", "54", "56", "+", "*"]
    • 下一个字符是 /,其优先级小于栈顶运算符 * 的优先级,将 * 弹出并添加到 output 中,output = ["5", "54", "56", "+", "*"] 将 / 压入 stack 数组中,stack = ["/"]
    • 下一个字符是 6,将其转换为字符串并添加到 output 中,output = ["5", "54", "56", "+", "*", "6"]
  3. 遍历完中缀表达式 main 后,stack 数组中还剩下一个运算符 /,将其弹出并添加到 output 数组中,output = ["5", "54", "56", "+", "*", "6", "/"]
  4. 最后,output 数组即为转换完成的后缀表达式,即 ["5", "54", "56", "+", "*", "6", "/"]

我们的大概运算就是这个样子 希望可以理解 接下来是全部的js代码

const display = document.querySelector('#display');
const buttons = document.querySelectorAll('button');

const themeToggleBtn = document.getElementById('theme-toggle');
const calculator = document.querySelector('.calculator');
let isDark = true;

themeToggleBtn.addEventListener('change', () => {
    calculator.classList.toggle('dark');
    isDark = !isDark;
});

function cum(){
    var main = display.innerText;
    var check = Ex(main);
    document.querySelector('#display').innerText = check;
}


function Ex(main) {
    var post = fix(main);
    var stack = [];

    for (var i = 0; i < post.length; i++) {
        var taken = post[i];

        if (!isNaN(taken)) {
            stack.push(parseFloat(taken))
        } else {
            var shu2 = stack.pop();
            var shu1 = stack.pop();

            switch (taken) {
                case '+':
                    stack.push(shu1 + shu2);
                    break;
                case '-':
                    stack.push(shu1 - shu2);
                    break;
                case '*':
                    stack.push(shu1 * shu2);
                    break;
                case '/':
                    stack.push(shu1 / shu2);
                    break;
            }
        }
    }

    return stack.pop()
}


function fix(main) {
    var output = [];
    var stack = [];

    for (var i = 0; i < main.length; i++) {
        var taken = main[i];
        if (!isNaN(taken)) {
            var number = "";

            while (!isNaN(taken) || taken === '.') {
                number += taken;
                i++;
                taken = main[i];
            }
            output.push(number);
            i--;
        } else if (taken === '(') {
            stack.push(taken);
        } else if (taken === ")") {
            while (stack.length > 0 && stack[stack.length - 1] !== '(') {
                output.push(stack.pop());
            }
            stack.pop(); 
        } else {
            while (stack.length > 0 && fuhao(stack[stack.length - 1]) >= fuhao(taken)) {
                output.push(stack.pop());
            }
            stack.push(taken);
        }
    }
    while (stack.length > 0) {
        output.push(stack.pop());
    }
    console.log(output);
    return output;
}




function fuhao(opter){
    switch(opter){
        case'+':
        case'-':
        return 1;
        case'*':
        case'/':
        return 2;
        default:
            return 0;
    }
}

buttons.forEach((item) => {
    item.onclick = () => {
        if (item.id == 'clear'){
            display.innerText = '';
        } else if (item.id == 'backspace'){
            let string = display.innerText.toString();
            display.innerText = string.substr(0, string.length - 1);
        } else if (display.innerText != '' && item.id =='equal'){
            cum();
        } else if (display.innerText == '' && item.id == 'equal'){
            display.innerText = 'Empty!';
            setTimeout(() => (display.innerText = ''), 2000);
        } else {
            display.innerText += item.id;
        }
    }
})

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值