0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptで電卓を作る2

Last updated at Posted at 2025-12-14

JavaScriptで電卓を作る②

「➖(マイナス)」を符号か演算子か正しく扱う」 🧮

CleanShot 2025-12-10 at 06.34.53@2x.png

こんにちは。tushiko23 です 👋
今回は、前回の記事の続きとして -(マイナス)の入力処理と計算処理 について書いていきます。

👉 前回の記事はこちら JavaScriptで電卓を作る①

今回やること 🧩

電卓を実装していると、- はとても厄介です。

3 - 1 の - → 引き算(演算子)

2 × -4 の - → 符号(マイナス)

今回はこの
👉 「-を演算子として扱うのか、符号として扱うのか」
を正しく判定する仕組みを実装していきます。

マイナス以外の演算子の方針 ✖️➗

まずは前提ルールです。

  • 画面上では × ÷ を表示

  • 内部計算では * / を使う

  • 演算子が連続で押された場合は 最後の演算子で上書き

3 → + → 3+ → × → 3×

演算子入力の処理(前回の復習)📥

function inputOperator(op) {
  const value = display.value;
  const lastRaw = value.slice(-1);

  if (value === "0では除算できません") {
    display.value = "0";
    return;
  }

  // 表示用 → 内部用
  const toInternal = (c) => {
    if (c === "×") return "*";
    if (c === "÷") return "/";
    return c;
  };
  const last = toInternal(lastRaw);

  // 内部用 → 表示用
  const toDisplay = (c) => {
    if (c === "*") return "×";
    if (c === "/") return "÷";
    return c;
  };
  const opForDisplay = toDisplay(op);

  // 0 の時は - を符号として許可
  if (display.value === "0" && op === "-") {
    display.value = "-";
    return;
  }

  if ("+-*/".includes(last)) {
    // - を符号として許可するケース
    if (op === "-" && last !== "-") {
      display.value += "-";
      return;
    }

    // 連続する演算子を整理
    let trimmed = value;
    while ("+-*/".includes(toInternal(trimmed.slice(-1)))) {
      trimmed = trimmed.slice(0, -1);
    }
    display.value = trimmed + opForDisplay;
    return;
  }

  display.value += opForDisplay;
}

連続演算子を整理する処理の中身 🔍

例えば、ユーザーが次のように入力したとします。

3 + - ×

内部では一度

"3+-×"

という文字列になります。

この状態では計算できないので、
末尾が演算子の間は1文字ずつ削除する 処理を行います。

while処理の流れ

1️⃣ "3+-×" → × 削除
2️⃣ "3+-" → - 削除
3️⃣ "3+" → + 削除
4️⃣ "3" → 数字なので終了

最終的に

display.value = "3×";

👉 計算可能な形だけを残す というわけです 👍

ここからが本題:- を符号か演算子か判定する 🧠

次は 「計算する直前」 の処理です。

① まずは式を分解する 🧩

const exprDisplay = display.value;
const exprForCalc = exprDisplay.replace(/×/g, "*").replace(/÷/g, "/");
let tokens = exprForCalc.match(/(\d+(?:\.\d+)?|[+\-*/])/g);


3 - 1 + 2 × -4 ÷ 2

👇 内部処理用に変換すると

tokens = ['3','-','1','+','2','*','-','4','/','2']

この時点では、- はすべて 演算子扱い です。

② - を符号か演算子か判定する関数 🧠

function mergeUnaryMinus(tokens) {
  const result = [];

  for (let i = 0; i < tokens.length; i++) {
    const t = tokens[i];
    const prev = result[result.length - 1];
    const next = tokens[i + 1];

    if (
      t === "-" &&
      next !== undefined &&
      !isNaN(Number(next)) &&
      (i === 0 || ["+", "-", "*", "/"].includes(prev))
    ) {
      // 符号として扱う
      result.push("-" + next);
      i++;
    } else {
      result.push(t);
    }
  }

  return result;
}

判定ルールを日本語で言うと ✍️

ー (マイナス) が 符号 になるのは次の条件すべてを満たすときです。

  • 今見ているのが

  • 次に数字がある かつ 式の先頭 または直前が演算子(+ - * /)

実際の処理結果 🔍

['3','-','1','+','2','*','-','4','/','2']

👇 mergeUnaryMinus 実行後

['3','-','1','+','2','*','-4','/','2']

👉 -4 が 1つの数値として扱える配列 になります 🎉

次回予告 🚀

次回はこの配列を使って

1️⃣ * / を優先して計算
2️⃣ 残った + - を左から計算
3️⃣ = を押したら結果を表示

という 本格的な計算処理 を実装していきます。

ここまでお読みいただきありがとうございました 🙇
「電卓ってこうやって作られてるんだ!」と感じてもらえたら嬉しいです!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?