求助:实现计算器多步连续运算功能|The Odin Project 练习
计算器多步运算实现与优先级问题解答
我正在完成The Odin Project的计算器练习,基础功能已接近完成(仅少量bug),但不知如何实现最后一项多步运算功能。
练习要求:
用户可连续执行多个运算,每次仅计算一对数字。例如12 + 7 - 5 * 3 = 应得出42。
计算器每次仅计算一对数字:如按下12、+、7、-,需先计算12+7得19并显示,再将19作为新计算的首个数字搭配-继续运算。
目前我的计算器无法实现该功能,同时疑惑是否需处理乘除优先于加减的优先级,恳请指点。
我的代码
HTML
<!DOCTYPE html> <html lang="en"> <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"> <link rel="stylesheet" href="styles.css"> <script src="main.js" defer></script> <title>Calculator</title> </head> <body> <div class="calcContainer"> <div class="output-clear-container"> <div class="output"> <div class="prev-result"></div> <div class="current-result">0</div> </div> <button class="clear">AC</button> </div> <div class="par"> <button class="number">7</button> <button class="number">8</button> <button class="number">9</button> <button class="operator clr">÷</button> </div> <div class="par"> <button class="number">4</button> <button class="number">5</button> <button class="number">6</button> <button class="operator clr">x</button> </div> <div class="par"> <button class="number">1</button> <button class="number">2</button> <button class="number">3</button> <button class="operator clr">-</button> </div> <div class="par"> <button class="decimal clr">.</button> <button class="number">0</button> <button class="equal clr">=</button> <button class="operator clr">+</button> </div> </div> </body> </html>
CSS
body { width: 100vw; height: 100vh; display: flex; justify-content: center; align-items: center; } .calcContainer { background: linear-gradient(276deg, #40a179, #77cea9); padding: 1em; border-radius: 5px; border: 1px solid #000; } button { padding: 1em; margin: 0.1em; width: 40px; background: #a2ffaf; border: 1px solid #fff; border-radius: 3px; cursor: pointer; } button:hover { background: #72e782; } .clr { background: #87e4bd; } .clr:hover { background: #53ad88; } .clear { margin: 0em 0.1em 0.5em 0.5em; padding: 0; } .output-clear-container { display: flex; } .output { flex-grow: 1; height: 40px; background: #c2fcca; border-radius: 5px; border: 1px solid #fff; display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; padding-right: 0.5em; margin-bottom: 0.5em; } .par { margin-bottom: 0.3em; } .prev-result { font-size: 14px; padding-bottom: 0.3em; color:#40a179; } .current-result { font-size: 18px; }
JavaScript
const displayPrevResult = document.querySelector('.prev-result'); const displayCurrentResult = document.querySelector('.current-result'); const equal = document.querySelector('.equal'); const decimal = document.querySelector('.decimal'); const clear = document.querySelector('.clear'); const numberBtn = document.querySelectorAll('.number'); const operatorBtn = document.querySelectorAll('.operator'); let current = ''; let previous = ''; let opString = ''; numberBtn.forEach((button) => { button.addEventListener('click', (e) => { getNum(e.target.textContent); }) }) operatorBtn.forEach((button) => { button.addEventListener('click', (e) => { getOp(e.target.textContent); }) }) clear.addEventListener('click', clearCalc); // Operate when clicking equal equal.addEventListener('click', () => { current = parseFloat(current); previous = parseFloat(previous); if (opString === '+') { current = add(previous, current); } else if (opString === '-') { current = subtract(previous, current); } else if (opString === 'x') { current = multiply(previous, current); } else if (opString === '÷') { if (current === 0) { clearCalc(); displayCurrentResult.textContent = 'ERROR'; return; } current = divide(previous, current); } displayCurrentResult.textContent = current; }) function clearCalc() { current = ''; previous = ''; displayCurrentResult.textContent = '0'; displayPrevResult.textContent = ''; } // Store current number, get operator and display it function getOp(opStr) { opString = opStr; previous = current; displayPrevResult.textContent = previous; current = ''; } // Get the number and display it function getNum(num) { current += num; displayCurrentResult.textContent = current; } // Operating functions function add(a, b) { return a + b; } function subtract(a, b) { return a - b; } function multiply(a, b) { return a * b; } function divide(a, b) { return a / b; } function operate(a, b) { return divide(b, a); } console.log(operate(22, 4));
问题解答
一、多步运算功能实现
当前代码仅在点击=时执行计算,要实现连续运算,需在点击下一个运算符时就完成上一次的计算,修改getOp函数并优化equal点击逻辑:
- 修改
getOp函数:
function getOp(opStr) { // 已有运算数据时,先完成上一次计算 if (previous !== '' && current !== '') { current = parseFloat(current); previous = parseFloat(previous); if (opString === '+') { current = add(previous, current); } else if (opString === '-') { current = subtract(previous, current); } else if (opString === 'x') { current = multiply(previous, current); } else if (opString === '÷') { if (current === 0) { clearCalc(); displayCurrentResult.textContent = 'ERROR'; opString = opStr; previous = ''; current = ''; return; } current = divide(previous, current); } // 更新显示与状态 displayCurrentResult.textContent = current; previous = current.toString(); current = ''; } // 记录新运算符 opString = opStr; // 首次点击运算符时赋值previous if (previous === '') { previous = current; displayPrevResult.textContent = previous; current = ''; } else { displayPrevResult.textContent = `${previous} ${opString}`; } }
- 优化
equal点击事件:
equal.addEventListener('click', () => { if (previous === '' || current === '') return; // 避免空值计算 current = parseFloat(current); previous = parseFloat(previous); if (opString === '+') { current = add(previous, current); } else if (opString === '-') { current = subtract(previous, current); } else if (opString === 'x') { current = multiply(previous, current); } else if (opString === '÷') { if (current === 0) { clearCalc(); displayCurrentResult.textContent = 'ERROR'; return; } current = divide(previous, current); } displayCurrentResult.textContent = current; // 将结果设为previous,支持后续继续运算 previous = current.toString(); opString = ''; displayPrevResult.textContent = ''; })
二、运算优先级处理
根据练习要求,计算器需要按输入顺序依次计算每一对数字,不需要处理乘除优先于加减的优先级。示例12 +7 -5 *3会按以下步骤计算:
- 12+7=19
- 19-5=14
3.14*3=42
如果后续要实现符合数学优先级的计算器,可使用后缀表达式(逆波兰表达式)或递归解析,但这超出了当前练习的要求。
三、额外小优化
添加小数输入限制(避免多次输入小数点):
decimal.addEventListener('click', () => { if (!current.includes('.')) { current += '.'; displayCurrentResult.textContent = current; } })
内容的提问来源于stack exchange,提问作者Quickpois0n
相关产品推荐
相关产品推荐

