You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React计算器连续输入多运算符时负号追加逻辑问题求助

React计算器连续运算符处理:负号与链式运算兼容问题

我用ReactJS开发计算器,大部分功能正常,但需要实现连续输入2个及以上运算符时,将负号追加到下一个操作数的逻辑,比如输入"5 * - 5"要输出"-25"而非"0"。

现有代码中,我尝试修改chooseOperation方法实现该逻辑,能处理简单的"8 * - 5 = -40",但链式运算曾出问题,添加&& current === ""后链式运算恢复,却卡在freeCodeCamp的测试用例:输入序列"5 * - + 5"需输出"10",这是最后未通过的测试。

原始核心代码

class Calculator extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      previous: "",
      current: "",
      operation: "",
    };
  }

  clear = () => {
    this.setState(() => ({
      previous: "",
      current: "0",
      operation: null,
    }));
  };

  delete = () => {
    this.setState((prevState) => ({
      current: prevState.current.slice(0, -1),
    }));
  };

  appendNumber = (number) => {
    const { current } = this.state;
    if (current === "0") {
      this.delete();
    }
    if (number === "." && current.includes(".")) return;
    this.setState(
      (prevState) => ({
        current: prevState.current + number,
      })
    );
  };

  chooseOperation = (op) => {
    const { previous, current, operation } = this.state;
    if (previous !== "" && current !== "") {
      this.compute();
    }

    this.setState(
      (prevState) => ({
        operation: op,
        previous:
          prevState.current === "" ? prevState.previous : prevState.current,
        current: "",
      })
    );
  };

  compute = () => {
    let computation;
    const { previous, current, operation } = this.state;
    const prev = parseFloat(previous);
    const curr = parseFloat(current);
    if (isNaN(previous) || isNaN(current)) return;
    let factorial = (n) => (n === 1 ? n : n * factorial(n - 1));
    switch (operation) {
      case "+":
        computation = prev + curr;
        break;
      case "-":
        computation = prev - curr;
        break;
      case "*":
        computation = prev * curr;
        break;
      case "÷":
        computation = prev / curr;
        break;
      case "!":
        computation = factorial(prev);
        break;
      case "√":
        computation = Math.sqrt(prev);
        break;
      case "log":
        computation = Math.log(prev);
        break;
      case "sin":
        computation = Math.sin(prev * (Math.PI / 180));
        break;
      default:
        return;
    }

    this.setState({
      current: computation,
      operation: "",
      previous: "",
    });
  };
}

我尝试过的修改

chooseOperation = (op) => {
    const { previous, current, operation } = this.state;
    if (previous !== "" && current !== "") {
      this.compute();
    }

    if (operation !== "" && op === "-" && previous !== "" && current === "") {
      this.setState((prevState) => ({
        current: "-",
        previous: prevState.previous,
        operation: prevState.operation,
      }));
    } else {
      this.setState(
        (prevState) => ({
          operation: op,
          previous:
            prevState.current === "" ? prevState.previous : prevState.current,
          current: "",
        })
      );
    }
  };

解决方案:优化chooseOperation逻辑

问题出在现有逻辑未覆盖「输入负号后又切换其他运算符」的场景,比如"5 * - + 5"中,输入"+"时当前current是"-",需要判断这种情况并调整运算符,而非直接触发计算或覆盖状态。修改后的chooseOperation方法如下:

chooseOperation = (op) => {
  const { previous, current, operation } = this.state;

  // 仅当current是有效数字时才触发计算,避免负号被误判为有效操作数
  if (previous !== "" && current !== "" && current !== "-") {
    this.compute();
  }

  // 场景1:已有运算符且当前无输入,输入负号 → 标记下一个操作数为负数
  if (operation !== "" && op === "-" && current === "") {
    this.setState({ current: "-" });
    return;
  }

  // 场景2:当前仅输入了负号(未输入数字),切换其他运算符 → 替换原有运算符,清空负号标记
  if (current === "-" && op !== "-") {
    this.setState({
      operation: op,
      current: ""
    });
    return;
  }

  // 常规场景:更新运算符,将当前输入转为previous,清空current
  this.setState(prevState => ({
    operation: op,
    previous: prevState.current === "" ? prevState.previous : prevState.current,
    current: ""
  }));
};

逻辑说明

  1. 计算条件优化:添加current !== "-",避免把单独的负号当作有效操作数触发计算
  2. 负号标记逻辑:已有运算符且当前无输入时,输入负号直接设置current为"-",保留原有运算符
  3. 运算符切换处理:如果当前仅输入了负号就切换其他运算符,直接替换运算符并清空负号标记,保证后续输入的数字和新运算符结合
  4. 常规流程保留:其他情况保持原有逻辑,确保链式运算正常

测试用例验证

  • "5 * - + 5"流程:
    1. 输入5 → current="5"
    2. 输入* → previous="5",operation="*",current=""
    3. 输入- → current="-"(触发场景1)
    4. 输入+ → 触发场景2,operation="+",current=""
    5. 输入5 → current="5"
    6. 按等号 → 计算5+5=10,符合要求
  • "5 * -5"流程:
    1. 输入5 → current="5"
    2. 输入* → previous="5",operation="*",current=""
    3. 输入- → current="-"
    4. 输入5 → current="-5"
    5. 按等号 → 5*-5=-25,正确

内容的提问来源于stack exchange,提问作者donjoe21915

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 21:17:25