以下为ChatGPT自动生成的解答,正确与否请自行判断。 也许你也可以从大家的发帖中找到想要的答案!
BFE.devAI解答 - JavaScript 代码题
124. 四则运算的结果
思路: 首先,我们需要将字符串转换成tokens,处理的方式参考119. 创建一个tokenizer ,即去掉空白字符后,将整个字符串分割成若干个token。
接下来,我们需要考虑计算的步骤,我们可以通过两个栈来实现,一个栈用来存储数字,另一个栈用来存储运算符号。从左到右遍历tokens,对于每个token,执行以下操作:
- 如果当前token是数字,将其压入数字栈中。
- 如果当前token是运算符号,分两种情况:
- 如果当前运算符号是左括号
(
,将其压入运算符号栈中。 - 如果当前运算符号是右括号
)
,则反复弹出运算符号栈中的元素,直到遇到左括号为止。在此过程中,从数字栈中弹出两个数字并执行相应运算,将结果压回数字栈中。 - 如果当前运算符号不是左括号或右括号,则将其与运算符号栈栈顶元素进行比较,如果当前运算符的优先级不高于栈顶运算符的优先级,则从数字栈中弹出两个数字并执行栈顶运算符的相应运算。将结果压回数字栈中。重复比较操作直到当前运算符的优先级高于栈顶运算符的优先级,然后将当前运算符压入运算符栈中。
- 如果当前运算符号是左括号
- 对于最后一个token,如果其是数字,则将其压入数字栈中,如果是运算符,执行与上一步类似的操作,直到所有的token处理完毕为止。
- 最后,从数字栈中弹出唯一的数字即为计算结果。
需要注意:
- 运算符的优先级,乘和除的优先级高于加和减。
- 当遇到除法计算时,需要判断除数是否为0。若为0,则返回Infinity或者- Infinity 。
- 当遇到负数计算时,需要处理负号,可以将减号判断是否是负号,若是,则将其转为减号。
- 当遇到多个连续的符号,可以将其当作一个符号处理,例如“- 1+23”即为“-1+23”。
完整代码:
function calculate(str) { // 将字符串转换成tokens const tokens = tokenize(str); // 运算符优先级 const priority = { '+': 1, '-': 1, '*': 2, '/': 2, }; // 数字栈和运算符栈 const numStack = []; const opStack = []; // 遍历tokens tokens.forEach(token => { if (isNumber(token)) { // 如果是数字,将其压入数字栈中 numStack.push(+token); } else if (token === '(') { // 如果是左括号,将其压入运算符栈中 opStack.push(token); } else if (token === ')') { // 如果是右括号,弹出运算符栈中的元素,并执行相应运算 while (opStack[opStack.length - 1] !== '(') { const op = opStack.pop(); const num2 = numStack.pop(); const num1 = numStack.pop(); numStack.push(calculateResult(num1, op, num2)); } opStack.pop(); // 弹出左括号 } else { // 如果是运算符,比较优先级,并执行相应运算 while ( opStack.length > 0 && opStack[opStack.length - 1] !== '(' && priority[token] <= priority[opStack[opStack.length - 1]] ) { const op = opStack.pop(); const num2 = numStack.pop(); const num1 = numStack.pop(); numStack.push(calculateResult(num1, op, num2)); } opStack.push(token); } }); // 处理剩余的运算符 while (opStack.length > 0) { const op = opStack.pop(); const num2 = numStack.pop(); const num1 = numStack.pop(); numStack.push(calculateResult(num1, op, num2)); } return numStack.pop();}// 判断一个token是否为数字function isNumber(token) { return /^\d+$/.test(token);}// 计算两个数字的运算结果function calculateResult(num1, op, num2) { let result; switch (op) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': if (num2 === 0) { return num1 > 0 ? Infinity : -Infinity; } result = num1 / num2; break; } return result;}// 将字符串转换成tokensfunction tokenize(str) { const tokens = []; let i = 0; while (i < str.length) { const char = str[i]; if (char === ' ') { // 跳过空格 i++; continue; } if (isNumberChar(char)) { // 合并数字字符 let j = i + 1; while (j < str.length && isNumberChar(str[j])) { j++; } tokens.push(str.slice(i, j)); i = j; continue; } // 处理连续的符号 if (char === '-' || char === '+') { if (isOp(tokens[tokens.length - 1]) || !tokens.length) { let j = i + 1; while (j < str.length && str[j] === char) { j++; } const sign = j % 2 === 0 ? '+' : char; tokens.push(sign); i = j; continue; } } // 其他情况直接作为token tokens.push(char); i++; } return tokens;}// 判断一个字符是否为数字字符function isNumberChar(char) { return /\d/.test(char);}// 判断一个token是否为运算符function isOp(token) { return ['+', '-', '*', '/', '(', ')'].indexOf(token) !== -1;}