当前位置:首页 > JavaScript

js用栈实现计算器

2026-03-02 01:28:58JavaScript

使用栈实现计算器的思路

利用栈可以高效处理表达式中的运算符优先级和括号嵌套问题。核心思路是将中缀表达式转换为后缀表达式(逆波兰表达式),再通过栈计算后缀表达式的值。

中缀转后缀的算法步骤

初始化一个运算符栈和一个输出队列(或数组)。从左到右扫描中缀表达式:

遇到数字时直接加入输出队列。

遇到运算符时:

  • 若栈顶运算符优先级不低于当前运算符,弹出栈顶运算符并加入输出队列
  • 将当前运算符压入栈中

遇到左括号时直接压入栈中。

遇到右括号时:

  • 弹出栈顶运算符并加入输出队列,直到遇到左括号
  • 弹出左括号但不输出

计算后缀表达式的算法

初始化一个操作数栈。从左到右扫描后缀表达式:

遇到数字时压入操作数栈。

遇到运算符时:

  • 弹出栈顶两个数字
  • 按运算符计算(注意操作数顺序)
  • 将结果压回栈中

JavaScript实现代码

class Stack {
  constructor() {
    this.items = []
  }
  push(element) {
    this.items.push(element)
  }
  pop() {
    return this.items.pop()
  }
  peek() {
    return this.items[this.items.length - 1]
  }
  isEmpty() {
    return this.items.length === 0
  }
}

function infixToPostfix(infix) {
  const precedence = {'+':1, '-':1, '*':2, '/':2, '^':3}
  const stack = new Stack()
  let postfix = []

  for(let token of infix.match(/(\d+|\+|\-|\*|\/|\^|\(|\))/g)) {
    if(/\d+/.test(token)) {
      postfix.push(token)
    } else if(token === '(') {
      stack.push(token)
    } else if(token === ')') {
      while(stack.peek() !== '(') {
        postfix.push(stack.pop())
      }
      stack.pop() // 弹出左括号
    } else {
      while(!stack.isEmpty() && stack.peek() !== '(' && 
            precedence[stack.peek()] >= precedence[token]) {
        postfix.push(stack.pop())
      }
      stack.push(token)
    }
  }

  while(!stack.isEmpty()) {
    postfix.push(stack.pop())
  }

  return postfix
}

function evaluatePostfix(postfix) {
  const stack = new Stack()

  for(let token of postfix) {
    if(/\d+/.test(token)) {
      stack.push(parseFloat(token))
    } else {
      const b = stack.pop()
      const a = stack.pop()
      switch(token) {
        case '+': stack.push(a + b); break
        case '-': stack.push(a - b); break
        case '*': stack.push(a * b); break
        case '/': stack.push(a / b); break
        case '^': stack.push(Math.pow(a, b)); break
      }
    }
  }

  return stack.pop()
}

// 使用示例
const infix = "3+4*2/(1-5)^2"
const postfix = infixToPostfix(infix)
const result = evaluatePostfix(postfix)
console.log(result) // 输出3.5

处理负数的扩展

上述实现不支持负数开头表达式,需预处理:

function preprocessInfix(infix) {
  // 将"-"替换为"0-"当它是表达式开头或跟在"("后
  return infix.replace(/(^|\(|\+|\-|\*|\/|\^)\s*\-/g, '$10-')
}

// 使用示例
const infix = "-3+4*(-2)"
const processed = preprocessInfix(infix)
const postfix = infixToPostfix(processed)
const result = evaluatePostfix(postfix)
console.log(result) // 输出-11

注意事项

运算符优先级定义影响计算结果,需根据需求调整。

对于浮点数运算,需考虑精度问题,可使用toFixed等方法处理。

js用栈实现计算器

大数运算可能需要使用BigInt或其他大数库。

标签: 计算器js
分享给朋友:

相关文章

js实现倒计时

js实现倒计时

使用 setInterval 实现倒计时 通过 setInterval 定时器每秒更新剩余时间,适用于简单倒计时场景。 function countdown(seconds, callback) {…

js轮播图实现原理

js轮播图实现原理

轮播图的基本原理 轮播图通过动态切换显示的内容(图片、文本等)实现视觉上的滑动效果。核心原理是利用CSS和JavaScript控制元素的显示与隐藏,或通过变换位置实现滑动动画。 实现方法一:CSS…

js 实现分页

js 实现分页

实现分页的基本逻辑 分页功能通常需要后端返回数据总量或总页数,前端根据当前页码和每页条数截取对应数据。以下是一个基于JavaScript的简单分页实现方案: 前端分页实现 假设已有从后端获取的完整数…

利用js实现

利用js实现

使用 JavaScript 实现 在 JavaScript 中,可以通过多种方式实现功能,具体取决于需求。以下是几种常见的方法: 方法一:使用原生 JavaScript // 示例代码 funct…

js实现 功能

js实现 功能

在 JavaScript 中实现功能通常涉及多个关键步骤,具体取决于功能需求。以下是常见功能的实现方法和示例: 基本功能实现 使用函数封装逻辑是最直接的方式。例如,实现一个计算两数之和的函数: f…

js实现滚动

js实现滚动

实现滚动效果的方法 在JavaScript中实现滚动效果可以通过多种方式完成,以下是一些常见的方法: 使用window.scrollTo() window.scrollTo()方法可以将页面滚动到指…