JavaScript | 長整数リテラルで利用可能な演算子

JavaScript JavaScript
スポンサーリンク

BigInt と Number を安全に混ぜるための小さなライブラリ

/**
 * BigNumSafe.js
 * Number と BigInt を安全に混ぜるためのユーティリティ関数集
 * - 自動変換ルールつき
 * - 桁あふれや丸め誤差を防止
 * - 型エラーを自動検出
 */

//----------------------------------------------------------
// 1️⃣ 型チェックと安全変換
//----------------------------------------------------------

/**
 * 値を安全に BigInt に変換(整数 Number のみ許可)
 */
export function toBigIntSafe(value) {
  if (typeof value === "bigint") return value;
  if (typeof value === "number") {
    if (!Number.isInteger(value)) {
      throw new TypeError(`toBigIntSafe: 整数でない値 (${value}) は変換できません`);
    }
    return BigInt(value);
  }
  if (typeof value === "string" && /^[+-]?\d+$/.test(value)) {
    return BigInt(value);
  }
  throw new TypeError(`toBigIntSafe: 変換できない型 (${typeof value})`);
}

/**
 * 値を安全に Number に変換(安全範囲外は警告)
 */
export function toNumberSafe(value) {
  if (typeof value === "number") return value;
  if (typeof value === "bigint") {
    const num = Number(value);
    if (Math.abs(num) > Number.MAX_SAFE_INTEGER) {
      console.warn(`⚠️ 精度が失われる可能性があります: ${value}n`);
    }
    return num;
  }
  throw new TypeError(`toNumberSafe: 変換できない型 (${typeof value})`);
}

//----------------------------------------------------------
// 2️⃣ 自動演算(Number/BigInt 混在を安全に扱う)
//----------------------------------------------------------

/**
 * ルール:
 * - どちらかが BigInt なら BigInt 計算
 * - 両方 Number なら Number 計算
 */
function normalizeType(a, b) {
  const hasBig = typeof a === "bigint" || typeof b === "bigint";
  return hasBig
    ? [toBigIntSafe(a), toBigIntSafe(b), "bigint"]
    : [a, b, "number"];
}

export const SafeMath = {
  add(a, b) {
    const [x, y, type] = normalizeType(a, b);
    return type === "bigint" ? x + y : x + y;
  },
  sub(a, b) {
    const [x, y, type] = normalizeType(a, b);
    return type === "bigint" ? x - y : x - y;
  },
  mul(a, b) {
    const [x, y, type] = normalizeType(a, b);
    return type === "bigint" ? x * y : x * y;
  },
  div(a, b) {
    const [x, y, type] = normalizeType(a, b);
    if (y === 0n || y === 0) throw new Error("0で割ることはできません");
    // BigInt の場合は整数除算
    return type === "bigint" ? x / y : x / y;
  },
  mod(a, b) {
    const [x, y, type] = normalizeType(a, b);
    return type === "bigint" ? x % y : x % y;
  },
  pow(a, b) {
    const [x, y, type] = normalizeType(a, b);
    return type === "bigint" ? x ** y : x ** y;
  }
};

//----------------------------------------------------------
// 3️⃣ 比較系(型が違っても比較できる)
//----------------------------------------------------------
export const SafeCompare = {
  eq(a, b) {
    const [x, y] = normalizeType(a, b);
    return x === y;
  },
  lt(a, b) {
    const [x, y] = normalizeType(a, b);
    return x < y;
  },
  gt(a, b) {
    const [x, y] = normalizeType(a, b);
    return x > y;
  },
  le(a, b) {
    const [x, y] = normalizeType(a, b);
    return x <= y;
  },
  ge(a, b) {
    const [x, y] = normalizeType(a, b);
    return x >= y;
  }
};

//----------------------------------------------------------
// 4️⃣ 型を意識しない共通API(便利ショートカット)
//----------------------------------------------------------

export function auto(a, b, op) {
  const ops = {
    "+": SafeMath.add,
    "-": SafeMath.sub,
    "*": SafeMath.mul,
    "/": SafeMath.div,
    "%": SafeMath.mod,
    "**": SafeMath.pow
  };
  const fn = ops[op];
  if (!fn) throw new Error(`未対応の演算子: ${op}`);
  return fn(a, b);
}
JavaScript

使い方例

import { SafeMath, SafeCompare, auto } from "./BigNumSafe.js";

// ✅ 型混在でも自動で安全に処理
console.log(SafeMath.add(10n, 5));      // → 15n
console.log(SafeMath.div(7n, 3));       // → 2n(整数除算)
console.log(SafeMath.div(7, 3));        // → 2.3333333333333335(Number)
console.log(SafeCompare.eq(54, 54n));   // → true
console.log(SafeCompare.lt(2n, 5));     // → true

// ✅ auto() を使えば演算子文字列で処理できる
console.log(auto(2n, 3, "**"));         // → 8n
console.log(auto(2, 3, "**"));          // → 8

// ⚠️ 浮動小数を BigInt に混ぜるとエラー
try {
  SafeMath.add(1.5, 2n);
} catch (e) {
  console.error(e.message);
}
JavaScript

自動変換ルールまとめ

条件変換先備考
両方 NumberNumber 計算小数含めOK
片方 BigInt両方 BigInt に変換整数除算になる
小数を BigInt に混ぜたエラー丸め禁止
比較系(==, <, >自動で同じ型に揃える精度は保たれる
結果が安全範囲外(Number)警告を出す精度落ちに注意

特徴

✅ 自動で安全な型変換
✅ 小数の混入を検出
✅ BigInt 演算の整数除算を維持
✅ 精度ロスを警告
✅ Node.js/ブラウザ両対応

タイトルとURLをコピーしました