当前位置:首页 > JavaScript

js用栈实现计算器

2026-03-02 01:28:58JavaScript

使用栈实现计算器的思路

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

中缀转后缀的算法步骤

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

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

遇到运算符时:

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

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

js用栈实现计算器

遇到右括号时:

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

计算后缀表达式的算法

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

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

js用栈实现计算器

遇到运算符时:

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

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等方法处理。

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

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

相关文章

js实现报表

js实现报表

使用JavaScript实现报表 在JavaScript中实现报表功能可以通过多种方式完成,常见的方法包括使用原生JavaScript、第三方库(如Chart.js、D3.js)或结合后端数据渲染。以…

js实现预览

js实现预览

文件上传预览实现 使用JavaScript实现文件上传预览功能,可以通过FileReader对象读取文件内容并显示预览。以下代码支持图片、文本和PDF文件的预览: // HTML部分需要包含inpu…

js实现祖玛

js实现祖玛

实现祖玛游戏的核心思路 祖玛游戏的核心玩法是发射彩色珠子,形成三个或以上相同颜色的珠子即可消除。以下是使用JavaScript实现的基本框架。 游戏初始化 创建画布并初始化游戏状态: const…

js实现自举

js实现自举

实现 JavaScript 自举的方法 JavaScript 自举(Bootstrap)通常指通过 JavaScript 动态加载自身或依赖的脚本,实现运行时环境的初始化或扩展。以下是几种常见实现方式…

js节流实现

js节流实现

节流的概念 节流(Throttle)是一种限制函数执行频率的技术,确保函数在一定时间间隔内只执行一次。常用于滚动事件、窗口调整等高频触发的场景。 基础实现方法 使用时间戳判断是否执行函数:…

js 实现图片 放大

js 实现图片 放大

使用 CSS transform 实现图片放大 通过 CSS 的 transform: scale() 属性可以实现图片的平滑放大效果。结合 JavaScript 监听鼠标事件控制放大状态: con…