JavaScript | 数値の有効桁数を指定して文字列に変換(toPrecision() メソッド)

javascrpit JavaScript
スポンサーリンク

toPrecision は「有効桁数(significant digits)」を指定して数値を文字列にするメソッドです。まず感覚を掴んで、次に細かい挙動・注意点、最後に練習問題と(便利な)小さなユーティリティ例を載せます。

1. ざっくり説明(ワンフレーズ)

数値.toPrecision(n) は、その数値を 「先頭から数えて n 桁の有効桁数」 で表した文字列を返します。余分な桁は丸められ、足りない場合は 0 で埋められることがあります。場合によっては指数(1.23e+4)の形式で返ることもあります。

2. 基本の例(実際の JS 出力イメージ)

(48).toPrecision(3)        // "48.0"
48..toPrecision(2)         // "48"
48 .toPrecision(2)         // "48"  ← 数字リテラルに続く . は注意(後述)
(12345).toPrecision(3)     // "1.23e+4"  (指数表記になる例)
123.456.toPrecision(5)     // "123.46"   (四捨五入される)
0.0012345.toPrecision(2)   // "0.0012"   (小さい数は小数表記)
0.00012345.toPrecision(2)  // "1.2e-4"   (さらに小さいと指数表記)
(1.2345e+30).toPrecision(3)// "1.23e+30" (大きな数は指数表記)
NaN.toPrecision && NaN.toPrecision(3)      // "NaN"
Infinity.toPrecision && Infinity.toPrecision(3) // "Infinity"
123.456.toPrecision()      // "123.456"  (引数省略→そのまま文字列化)
JavaScript

3. どういうときに指数表記になるの?

  • toPrecision は「指定した有効桁数で表現する」ことが第一目標なので、桁数を満たすためや読みやすさのために指数(科学)表記を使うことがあります。
  • 簡単に言うと「とても大きい」「とても小さい」数や、指定した有効桁数で書くと桁が飛ぶ場合に指数表記になりやすいです。
    (実装細部や閾値はエンジンによって表示形式の細かいルールが異なる場合がありますが、結果の意味合いは同じです。)

4. 丸め(ラウンド)のルール

  • toPrecision は通常の四捨五入(round half away from zero に近い)で丸められます。
  • 有効桁数より桁数が少ない場合は、必要に応じて末尾に 0 を足して桁合わせします(例:(48).toPrecision(3)"48.0")。

5. 数字リテラルから直接呼ぶときの注意(初心者がよくハマる)

JavaScript の文法上、48.toPrecision(2) と書くと構文エラーになります(48. が小数点と解釈されるため)。回避法は次のいずれか:

  • 数字を括弧で囲む: (48).toPrecision(2)
  • ドットを二つ使う: 48..toPrecision(2) (最初の . は小数点、次の . がメソッドアクセス)
  • 数字のあとに空白を置く: 48 .toPrecision(2) も動きます(ただし可読性に注意)

6. toFixed / toExponential との違い(実務でよく出る比較)

  • toFixed(n) → 小数点以下 n 桁 を表示(小数点以下の桁数固定)。例:(1.2345).toFixed(2)"1.23". 主に「小数以下の桁数を揃えたい」時に使う。
  • toExponential(n)指数表記有効桁数 n を指定して表示。例:(12345).toExponential(3)"1.23e+4".
  • toPrecision(n)有効桁数 n を指定(整数部・小数部を合わせて n 桁)。要するに toFixedtoExponential の中間的な振る舞いをします。
    使い分け:人が読む通常の金額やパーセントは toFixed、科学計算や幅広い桁の値を扱うなら toPrecisiontoExponential

7. よくある疑問・落とし穴

  • toPrecision の戻り値は 文字列 です。数値として計算に戻すなら Number(...) 等で変換する必要があります。
  • 非整数や非正の桁数を渡すとどうなるか:エンジンにより挙動が異なる場合があります(丸められる・エラーになる等)。実際のコードではユーザー入力等で precision を受け取るなら Math.round / Math.max 等で検証してから渡すのが安全です。
  • 浮動小数点誤差との関係:内部は IEEE754 の浮動小数点なので、toPrecision の結果が「見た目上正しくても」内部値はわずかに違う場合があります(一般的な JS の数値の注意事項と同じ)。

8. 実際に手を動かす例

  1. (48).toPrecision(1)"5e+1" または "48"?
    実際は (48).toPrecision(1)"5e+1" になることがあります(有効桁1:48 ≈ 5×10¹)。
    ※ 表示のされ方はエンジンや実行環境(console)で若干差が出ることがある点に注意。
  2. (48).toPrecision(3)"48.0"(有効桁3:4 8 0
  3. (0.001234).toPrecision(2)"0.0012"
  4. (123456789).toPrecision(4)"1.235e+8"(小数第一位で四捨五入)

9. 小さなユーティリティ(「指数表記になったら展開してほしい」場合のベストエフォート関数)

指数表記が嫌で必ず普通の小数表記にしたい場合、完全に誤差なしで万能に直すのは地味に難しい(浮動小数点の限界のため)ですが、見た目を直す実用的な関数を示します。

// 注意: 完全に万能ではありませんが、一般的な見た目変換に使えます
function safeToPrecision(num, precision) {
  const s = Number(num).toPrecision(precision);
  if (!/e/i.test(s)) return s; // 指数表記でなければそのまま

  // 指数表記なら分解して普通の小数表記に変換(簡易実装)
  const m = s.match(/^([+-]?)(\d(?:\.\d+)?)e([+-]?\d+)$/i);
  if (!m) return s;
  const sign = m[1] || "";
  let mantissa = m[2].replace('.', '');
  const exp = parseInt(m[3], 10);
  if (exp >= 0) {
    // 小数点を右に移動
    const neededZeros = exp - (mantissa.length - 1);
    if (neededZeros >= 0) {
      return sign + mantissa + '0'.repeat(neededZeros);
    } else {
      const pos = (mantissa.length - 1) + exp;
      return sign + mantissa.slice(0, pos+1) + '.' + mantissa.slice(pos+1);
    }
  } else {
    // 小数点を左に移動
    return sign + '0.' + '0'.repeat(Math.abs(exp) - 1) + mantissa;
  }
}
JavaScript

使い方:

safeToPrecision(1.23e-4, 2)   // "0.000123"
safeToPrecision(1.23e+6, 3)   // "1230000"
JavaScript

(※注意:上の実装は「見た目」を整える目的の簡易コードです。非常に大きな指数や精度の極端なケースでは端数・丸めの扱いに注意が必要です。)

10. 練習問題(自力でやってみよう)

  • (5.6789).toPrecision(2) の結果は? → 答えを書いてから実行して確かめてください。
  • (0.00056789).toPrecision(2) は?
  • (999).toPrecision(1) は?(どう丸められるか考える)

まとめ(覚えるべきポイント)

  • toPrecision(n) = 有効桁数 n を指定して文字列にする。
  • 結果は文字列。丸めや 0 埋めが発生する。
  • 場合によって 指数表記 になる。
  • 数字リテラルに直接 . を続けると構文エラーになりやすいので (num).toPrecision() の形が安全。
  • 金額表示など「小数点以下を揃えたい」場合は toFixed の方がわかりやすい。
タイトルとURLをコピーしました