JavaScript における `Number` クラス
この記事ではJavaScript における Number クラスについて説明します。
Number の性質、よくある落とし穴、便利な API、実践的なサンプルを段階を踏んで丁寧に説明します。
YouTube Video
JavaScript における Number クラス
Number は JavaScript における基礎的な数値型であり、IEEE-754 倍精度浮動小数点(64-bit)で表現されます。
基本:数値の表現と型判定
JavaScript の数値はすべてプリミティブのnumber型で表されます。
1// Primitive numbers and Number object
2const a = 42; // primitive number
3const b = 3.14; // primitive float
4const c = Number(10); // primitive via constructor call (function form)
5const d = new Number(10); // Number object (wrapper)
6
7console.log(typeof a); // "number"
8console.log(typeof d); // "object"
9console.log(c == d); // true (value coerces)
10console.log(c === d); // false (different types)
- このコードは、プリミティブな
numberとNumberラッパーオブジェクトの差を示します。通常はラッパーを使わずプリミティブを用います。
特殊値:NaN、Infinity、定数
Number には特別な数値(NaN、Infinity)や定数が用意されています。
1// Special numeric values and constants
2console.log(Number.NaN); // NaN
3console.log(Number.POSITIVE_INFINITY); // Infinity
4console.log(Number.NEGATIVE_INFINITY); // -Infinity
5
6console.log(Number.MAX_VALUE); // largest positive representable
7console.log(Number.MIN_VALUE); // smallest positive representable (closest to 0)
8console.log(Number.MAX_SAFE_INTEGER); // 9007199254740991
9console.log(Number.MIN_SAFE_INTEGER); // -9007199254740991
10console.log(Number.EPSILON); // smallest difference ~2.220446049250313e-16
MAX_SAFE_INTEGER以上の整数は正確に表現できない場合があり、その必要がある場合はBigIntを検討します。EPSILONは浮動小数点比較で使います。
数値変換:Number()、parseInt、parseFloat、+ 演算子
文字列から数値への変換には複数の方法があり、それぞれ挙動が違います。
1// Converting strings to numbers
2console.log(Number("42")); // 42
3console.log(Number(" 3.14 ")); // 3.14
4console.log(+ "7"); // 7 (unary +)
5
6console.log(parseInt("42px")); // 42
7console.log(parseFloat("3.14abc"));// 3.14
8
9// Careful with parseInt and radix
10console.log(parseInt("08")); // 8
11console.log(parseInt("08", 10)); // 8 (explicit radix is safer)
Number()は文字列全体が厳密に数値形式でないとNaNを返しますが、parseIntとparseFloatは先頭から数値として読める部分を解析します。parseIntには必ず基数を与える習慣を付けると安全です。
NaN の扱いと判定:isNaN と Number.isNaN
NaN(Not-A-Number)は特殊で、NaN !== NaN になります。判定方法に差があり、グローバル isNaN は型変換を行うため誤検出があり、Number.isNaN を推奨します。
1// NaN detection differences
2console.log(NaN === NaN); // false
3
4console.log(isNaN("foo")); // true -> because "foo" coerces to NaN
5console.log(Number.isNaN("foo")); // false -> "foo" is not the numeric NaN
6
7console.log(Number.isNaN(NaN)); // true
- 数値チェックや演算結果の検証には
Number.isNaNを使い、不要な型変換を避けます。
浮動小数点の誤差と Number.EPSILON を使った比較
IEEE-754 のために 0.1 + 0.2 !== 0.3 のような誤差が発生します。厳密比較では差分と Number.EPSILON を使う方法が一般的です。
1// Floating point precision example and EPSILON comparison
2const sum = 0.1 + 0.2;
3console.log(sum === 0.3); // false
4
5function nearlyEqual(a, b, epsilon = Number.EPSILON) {
6 return Math.abs(a - b) <= epsilon * Math.max(1, Math.abs(a), Math.abs(b));
7}
8
9console.log(nearlyEqual(sum, 0.3)); // true
- 誤差を許容する比較を行う場合、絶対差だけでなくスケーリングを行う
nearlyEqualのような実装が堅牢です。
整数判定と安全な整数 (isInteger、isSafeInteger)
整数であるかどうかや、精度が保証される範囲かを確認する API があります。
1// Integer and safe integer checks
2console.log(Number.isInteger(3)); // true
3console.log(Number.isInteger(3.0)); // true
4console.log(Number.isInteger(3.1)); // false
5
6console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true
7console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false
- 大きな整数の正確性が必要なときは
Number.isSafeIntegerで検査し、超える場合はBigIntの利用を検討します。
表示とフォーマット:toFixed、toPrecision、toString
数値の表示を制御するメソッドが用意されています。toFixed は小数点以下桁数を指定して文字列を返しますが、丸めに注意が必要です。
1// Formatting numbers for display
2const x = 1.23456;
3console.log(x.toFixed(2)); // "1.23" (string)
4console.log(x.toPrecision(3)); // "1.23" (string with total significant digits)
5console.log((255).toString(16)); // "ff" (hexadecimal string)
toFixedは文字列を返すので、計算に利用する場合は変換した後の数値に注意してください。
文字列結合と + の注意点
+ 演算子は数値加算にも文字列連結にも使われるため、型に応じて意図しない結果が出ることがあります。
1// Pitfall with + operator and type coercion
2console.log(1 + 2 + "px"); // "3px"
3console.log("px" + 1 + 2); // "px12"
4console.log(1 + "2" - 0); // 3 (string coerced to number for subtraction)
- 文字列と数値が混在する場合は暗黙変換を避けるため
String()やNumber()、テンプレート文字列を明示的に使うと安全です。
高度なユースケース:Number.parseInt / Number.parseFloat、valueOf
Number.parseInt と Number.parseFloat はグローバル関数のエイリアスです。valueOf は Number オブジェクトからプリミティブ値を取り出すために使われますが、通常は必要ありません。
1// Number.parseInt/parseFloat aliases and valueOf example
2console.log(Number.parseInt("100", 10)); // 100
3console.log(Number.parseFloat("3.14")); // 3.14
4
5const nObj = new Number(5);
6console.log(nObj.valueOf()); // 5
7console.log(nObj + 1); // 6 (object coerced to primitive)
Number.parseIntとNumber.parseFloatを使うときも基数や入力のトリミングなどに気を付ける必要があります。ラッパーオブジェクトは通常避けます。
参考となる小さめのユーティリティ例:数値検証関数
よく使う判定をまとめた小さなユーティリティ関数を示します。これで入力検証などが楽になります。
1// Small number utility functions
2function toNumberStrict(value) {
3 // Return a Number or throw for invalid numeric strings
4 const n = Number(value);
5 if (typeof value === "string" && value.trim() === "") {
6 throw new Error("Empty string is not a valid number");
7 }
8 if (Number.isNaN(n)) {
9 throw new Error(`Invalid number: ${value}`);
10 }
11 return n;
12}
13
14function almostEqual(a, b, eps = Number.EPSILON) {
15 // Robust relative comparison
16 return Math.abs(a - b) <= eps * Math.max(1, Math.abs(a), Math.abs(b));
17}- これらは入力処理や比較で繰り返し使える汎用性の高い関数です。エラーを投げる実装はバリデーション用途で便利です。
パフォーマンスとベストプラクティスのまとめ
以下は、Numberを利用する際の実用的な点です。
- 基本はプリミティブ
numberを使い、new Number()は避けます。 - 文字列→数値変換は用途により
Number()(厳密)かparseInt/parseFloat(部分抽出)を使い分けます。 Number.isNaNとNumber.isFiniteを利用して安全にチェックします。- 浮動小数点比較は
Number.EPSILONを使うか専用の比較関数を作ります。 - 整数の正確さが必要な場合は
Number.isSafeIntegerを確認し、越えるならBigIntを使います。 - 表示用の丸めには
toFixedやtoPrecisionを使えますが、返り値が文字列であることに注意します。
まとめ
Number は JavaScript のすべての数値を扱う基本型であり、整数・小数・特殊値(NaN や Infinity)を含みます。型変換や浮動小数点の誤差に注意しつつ、Number.isNaN や Number.EPSILON などのメソッドを正しく使うことが重要です。安全な整数範囲を超える場合は BigInt を利用し、丸めや表示には toFixed や toPrecision を活用しましょう。
YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。