はじめに
JavaScriptの数値型「Number」は、整数も小数もすべて IEEE 754規格の倍精度浮動小数点数(64ビット) で表現されます。
つまり、1 も 3.14 も 9007199254740991 も、内部的には同じ形式で処理されるのです。
この「すべてをひとつの形式で扱う」という仕様はシンプルで便利な反面、数値誤差や表現できる範囲の制限といった問題の原因にもなります。
イティセル/コード専門官要するに、JavaScriptの「Number」は、整数型や小数型を分けずに ひとつの強力なフォーマット(倍精度浮動小数点数)に統一したものであり、それがそのまま「Number型」として定義されているのです。
IEEE 754倍精度浮動小数点数とは


IEEE 754は、コンピュータで実数を表現するための国際規格です。
その中で「倍精度(double precision)」と呼ばれる形式は64ビットを使い、次のように構成されています。
• 符号部(1ビット):数が正か負かを表す
• 指数部(11ビット):数の大きさ(2の何乗か)を決める
• 仮数部(52ビット):数の細かい部分(有効桁)を保持する
この仕組みによって、非常に広い範囲の数値を扱うことができます。
例えば、10の308乗といった巨大な数から、10のマイナス308乗のような極小の数まで表現可能です。



倍精度を使えば、10兆や1000京といった桁外れの数値も扱えます。制限はありますが、日常的なプログラミングではほとんど気にしなくてよいほど遠い範囲です。
ただし
64ビットという有限の枠に収めるため、0.1や0.2のように2進数で割り切れない数は近似値として保存されることになります。
その結果、JavaScriptでよく見られる 0.1 + 0.2 = 0.30000000000000004 のような誤差が生じるのです。
0.1 + 0.2 => 0.30000000000000004


整数は2進数で正確に表せるため誤差が出にくいですが、
小数は「2進数で無限に続く小数」になってしまうため、どうしても誤差が避けられないのです。
表現できる範囲と限界





JavaScriptの Number 型には表現できる最大値があります。
それが Number.MAX_VALUE ≈ 1.7976931348623157e+308 です。
この値を超えると、計算結果は Infinity(無限大) になります。
つまり「オーバーフローした」と捉えてよいでしょう。
最大値 ≈ 1.8 × 10^308
→ これ以上の数は「Infinity」になる。
console.log(Number.MAX_VALUE);
console.log(Number.MAX_VALUE * 2); 


1.7976931348623157e+308
Infinity
実行結果
1.7976931348623157e+308
Infinity


JavaScriptの Number 型で表現できる最小の正の値は Number.MIN_VALUE ≈ 5 × 10^-324 です。
これは「0より大きいが、これ以上小さくできない極限の値」です。
これより小さい数は、0として扱われてしまいます(アンダーフロー)。
最小の正の値 ≈ 5 × 10^-324
→ これより小さい正の数は「0」として扱われる。
console.log(Number.MIN_VALUE);
console.log(Number.MIN_VALUE / 2);


5e-324
0
実行結果
5e-324
0


最大値を超えると、1を足しても2を足しても結果はすべて Infinity となり、無限大に吹き飛んでしまいます。
逆に、最小の正の値を下回ると、1を引いても2を引いても結果はすべて 0 となり、ゼロに吸い込まれてしまいます。
さらに整数についても制約があり、安全に表現できるのは -(2^53 – 1) ~ (2^53 – 1) の範囲だけです。
安全に整数を表現できる範囲 -(2^53 – 1) ~ (2^53 – 1)
→ これを超えると「1刻みの差」を区別できなくなる。
console.log(Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2);


これを実行すると、
「9007199254740992 と 9007199254740992 は等しいか?」という判定になり、結果は…ぽちっ



true
実行結果
true


つまり、範囲を超えると +1 も +2 も同じ値に丸められてしまうため、true になるのです。
`NaN`や`Infinity`もIEEE 754由来





IEEE 754 では「数値演算の結果が通常の数値で表せない場合」に備えて、特別な値として Infinity や NaN が定義されています。
簡単にいうと、これらの「特殊値」は数の世界の 警備員 のような存在です。
Infinity:範囲を超えた計算結果



Infinity の警備員:「これ以上は増やせません!」と範囲を超えた数を止める。
console.log(1 / 0);


Infinity
実行結果
InfinityNaN (Not a Number):数値演算が不正な場合



NaN の警備員:「この計算は不正です!」と割り切れない演算を弾く。
console.log(0 / 0);


NaN
実行結果
NaN誤差を回避する方法


1. 丸め処理を行う



Numberは少数を正確に扱うのが苦手です。
例えば 0.1 + 0.2 を実行すると、本来の 0.3 ではなく 0.30000000000000004 という微妙な誤差が出てしまいます。
こうした誤差を避けるには、丸め処理を行う関数を用意して「小数点以下を何桁まで扱うか」を指定してあげるのが一般的です。
function round(num, digits) {
return Math.round(num * 10 ** digits) / 10 ** digits;
}
console.log(round(0.1 + 0.2, 2));


0.3
実行結果
0.32. 整数に変換して計算する



小数のまま計算すると誤差が出やすいため、いったん整数に変換してから計算し、最後に小数に戻すという方法もあります。とてもシンプルなやり方です。
console.log((0.1 * 10 + 0.2 * 10) / 10);


0.3
実行結果
0.33. BigIntを使う(整数のみ)



どうしても 9007199254740991(Number.MAX_SAFE_INTEGER) を超える整数を正確に扱いたい場合は、BigInt を使う方法があります。
BigInt を使うときは、数値リテラルの末尾に n を付けるのがルールです。
const big = 9007199254740991n + 2n;
console.log(big);


9007199254740993n
実行結果
9007199254740993n → 9007199254740991を超えてるまとめ


JavaScriptの Number 型は、整数も小数もすべてを IEEE 754 倍精度浮動小数点数 というひとつの器に押し込めた設計思想の産物です。
そのシンプルさは「1 も π も天文学的な数も同じ形式で扱える」という強みをもたらす一方で、誤差・範囲・精度という宿命的な制約を背負わせました。
• 誤差:0.1 + 0.2 が 0.3 にならないのは、2進数で有限表現できない小数を近似値で保存しているから。
• 範囲:最大値を超えれば Infinity に吹き飛び、最小値を下回れば 0 に吸い込まれる。
• 精度:整数も安全に扱えるのは ±(2^53 – 1) までで、それを超えると「+1」と「+2」の違いすら消えてしまう。
これらの“警備員”の存在を理解したうえで、丸め処理・整数変換・BigInt・専用ライブラリといった対策を適材適所で使い分けることが、堅牢な数値処理への第一歩です。
要するに、Number型は万能ではないが、その限界を知り、補う術を持てば十分に戦える武器になる。
もしこの記事が役に立ったと思ったら、シェアやコメントで教えてください。
いただいた声を今後の改善に活かしていきます。
最後まで読んでくださり、本当にありがとうございました。









コメント