JavaScriptの数値とMath
JavaScriptには数値型が1つだけあります:Numberです。整数でも小数でも、すべてNumberです。これはintやfloatを区別するJavaやCとは異なります。シンプルですが、いくつかの注意点があります。
Number型
JavaScriptでは、整数も浮動小数点数もNumber型です。整数専用の型はありません。
<script>
let a = 42; // これはNumber
let b = 3.14; // これもNumber
typeof a; // "number"
typeof b; // "number"
</script>
数値は他の形式でも記述できます:
<script>
let hex = 0xFF; // 16進数、255に等しい
let octal = 0o10; // 8進数、8に等しい
let binary = 0b1010; // 2進数、10に等しい
let big = 1e6; // 科学的記数法、1000000に等しい
</script>
NaNとInfinity
NaNは「Not a Number」の略ですが、型はNumberです — JavaScriptのもっとも皮肉な設計選択の一つです。
<script>
typeof NaN; // "number" ← そうです、実は数値です
NaN === NaN; // false ← 自分自身とも等しくない!
Number.isNaN(NaN); // true ← このメソッドでNaNをチェックする
</script>
NaNはいつ出現するのでしょう?数値でないもので計算をしようとしたときです:
<script>
parseInt('abc'); // NaN
'hello' * 5; // NaN
Math.sqrt(-1); // NaN
</script>
Infinityは正の無限大を表し、ゼロで割ったときに現れます:
<script>
1 / 0; // Infinity
-1 / 0; // -Infinity
typeof Infinity; // "number"
</script>
💪 NaNかどうかをチェックするには、
===を絶対に使わずNumber.isNaN()を使いましょう。NaN === NaNがfalseなので、これは無数の開発者が引っかかってきた落とし穴です。
浮動小数点の精度
これはJavaScriptのもっとも有名な癖です:0.1 + 0.2 !== 0.3。
<script>
0.1 + 0.2; // 0.30000000000000004
0.1 + 0.2 === 0.3; // false
</script>
理由は、コンピュータが浮動小数点数をバイナリで保存する方法に関係しています。値0.1はバイナリでは循環小数となり、保存時に精度が失われます。これはJavaScriptに特有の問題ではなく、IEEE 754標準を使用するすべての言語に存在します。
対策:toFixed()でフォーマットするか、計算前にスケールアップします:
<script>
(0.1 + 0.2).toFixed(2); // "0.30"
(0.1 * 100 + 0.2 * 100) / 100; // 0.3
</script>
実例:精度問題デモ
<!DOCTYPE html>
<html>
<body>
<h2>浮動小数点の精度問題</h2>
<p id="output"></p>
<script>
let html = '';
html += '0.1 + 0.2 = ' + (0.1 + 0.2) + '<br>';
html += '0.1 + 0.2 === 0.3 ? ' + (0.1 + 0.2 === 0.3) + '<br><br>';
html += '<strong>対策1: toFixed</strong><br>';
html += '(0.1 + 0.2).toFixed(2) = ' + (0.1 + 0.2).toFixed(2) + '<br><br>';
html += '<strong>対策2: スケールアップしてからダウン</strong><br>';
html += '(0.1*100 + 0.2*100)/100 = ' + ((0.1 * 100 + 0.2 * 100) / 100) + '<br><br>';
html += '<strong>NaN関連:</strong><br>';
html += 'parseInt("abc") = ' + parseInt('abc') + '<br>';
html += 'NaN === NaN ? ' + (NaN === NaN) + '<br>';
html += 'Number.isNaN(NaN) ? ' + Number.isNaN(NaN) + '<br><br>';
html += '<strong>Infinity関連:</strong><br>';
html += '1 / 0 = ' + (1 / 0) + '<br>';
html += 'typeof Infinity = ' + typeof Infinity;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
Mathオブジェクト
MathはJavaScriptの組み込み数学ユーティリティです。インスタンス化は不要で、直接メソッドを呼び出します:
| メソッド/プロパティ | 用途 | 例 |
|---|---|---|
Math.round() |
最も近い整数に四捨五入 | Math.round(4.6) → 5 |
Math.floor() |
切り捨て | Math.floor(4.9) → 4 |
Math.ceil() |
切り上げ | Math.ceil(4.1) → 5 |
Math.random() |
0〜1の乱数 | Math.random() → 0.3721... |
Math.max() |
最大値 | Math.max(1,5,3) → 5 |
Math.min() |
最小値 | Math.min(1,5,3) → 1 |
Math.PI |
円周率 | 3.141592653589793 |
Math.abs() |
絶対値 | Math.abs(-7) → 7 |
Math.pow() |
べき乗 | Math.pow(2,3) → 8 |
Math.sqrt() |
平方根 | Math.sqrt(16) → 4 |
実例:主要なMathメソッド
<!DOCTYPE html>
<html>
<body>
<h2>Mathオブジェクトのメソッド</h2>
<p id="output"></p>
<script>
let html = '';
html += 'Math.round(4.6) = ' + Math.round(4.6) + '<br>';
html += 'Math.round(4.4) = ' + Math.round(4.4) + '<br>';
html += 'Math.floor(4.9) = ' + Math.floor(4.9) + '<br>';
html += 'Math.ceil(4.1) = ' + Math.ceil(4.1) + '<br>';
html += 'Math.abs(-7) = ' + Math.abs(-7) + '<br>';
html += 'Math.pow(2, 10) = ' + Math.pow(2, 10) + '<br>';
html += 'Math.sqrt(144) = ' + Math.sqrt(144) + '<br>';
html += 'Math.max(1, 5, 3) = ' + Math.max(1, 5, 3) + '<br>';
html += 'Math.min(1, 5, 3) = ' + Math.min(1, 5, 3) + '<br>';
html += 'Math.PI = ' + Math.PI + '<br>';
let radius = 5;
let area = Math.PI * Math.pow(radius, 2);
html += `半径${radius}の円の面積 = ${area.toFixed(2)}`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
💪
Math.round(-1.5)は-2ではなく-1を返します。負の境界での四捨五入の動作は直感に合わないことがあります。覚えておきましょう。
toFixed() — 小数のフォーマット
toFixed(n)は数値を小数点以下n桁にフォーマットし、文字列を返します:
<script>
let price = 9.9;
price.toFixed(2); // "9.90" ← 注意:文字列を返す
+(9.9).toFixed(2); // 9.9 ← +で数値に戻す
</script>
toFixedは文字列を返します!その後さらに計算する必要がある場合は、数値に変換し直しましょう。
toString() — 基数変換
数値メソッドtoString(radix)は数値を指定された基数の文字列に変換します:
<script>
(255).toString(16); // "ff" 16進数
(255).toString(2); // "11111111" 2進数
(255).toString(8); // "377" 8進数
(100).toString(); // "100" 10進数(デフォルト)
</script>
実例:基数変換
<!DOCTYPE html>
<html>
<body>
<h2>基数変換</h2>
<p id="output"></p>
<script>
let num = 255;
let html = `数値${num}の異なる基数表現:<br><br>`;
html += `10進数: ${num.toString()}<br>`;
html += `2進数: ${num.toString(2)}<br>`;
html += `8進数: ${num.toString(8)}<br>`;
html += `16進数: ${num.toString(16)}<br><br>`;
let price = 19.9;
html += `価格フォーマット: $${price.toFixed(2)}<br>`;
html += `toFixedの戻り値型: ${typeof price.toFixed(2)}<br>`;
document.getElementById('output').innerHTML = html;
</script>
</body>
</html>
Math.random() — 乱数の生成
Math.random()は0(以上)から1(未満)のランダムな浮動小数点数を返します。実際には、特定の範囲内のランダムな整数が必要になることが多いです:
<script>
// minからmax(両端含む)までのランダムな整数を生成
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>
実例:乱数デモ
<!DOCTYPE html>
<html>
<body>
<h2>乱数生成器</h2>
<button onclick="rollDice()">サイコロを振る</button>
<button onclick="pickLotto()">数字を選ぶ (1-35)</button>
<p id="output"></p>
<script>
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function rollDice() {
let dice = getRandomInt(1, 6);
let dots = '';
for (let i = 0; i < dice; i++) {
dots += ' ⚀';
}
document.getElementById('output').innerHTML =
`出た目: <strong>${dice}</strong>${dots}`;
}
function pickLotto() {
let numbers = [];
while (numbers.length < 5) {
let n = getRandomInt(1, 35);
if (!numbers.includes(n)) {
numbers.push(n);
}
}
numbers.sort((a, b) => a - b);
document.getElementById('output').innerHTML =
`あなたのラッキーナンバー: <strong>${numbers.join(' ')}</strong>`;
}
</script>
</body>
</html>
💪
Math.random()は擬似乱数を生成するため、暗号用途には適していません。暗号学的に安全な乱数にはcrypto.getRandomValues()を使いましょう。
📖 まとめ
- JavaScriptには
Number型が1つだけで、整数も小数もNumber NaNはどの値とも等しくない(自分自身も含む)。検出にはNumber.isNaN()を使う0.1 + 0.2 !== 0.3は精度の問題で、toFixed()やスケールアップ/ダウンで対策するMath.floorは切り捨て、Math.ceilは切り上げ、Math.roundは四捨五入- ランダムな整数の公式:
Math.floor(Math.random() * (max - min + 1)) + min toFixed()は文字列を返す — さらに計算する場合は数値に戻す
❓ よくある質問
Math.round(2.5)とMath.round(-2.5)はそれぞれいくつですか?Math.round(2.5)は3、Math.round(-2.5)は-2です。小数部分がちょうど.5のとき、JavaScriptは正の無限大の方向に丸めるため、正の数と負の数の両方がゼロに近い方に丸められます。Number.isFinite(value)を使います。NaN、Infinity、-Infinityを除外し、数値型以外も拒否します。グローバルのisFinite()も使えますが、型チェックをしません(先に型変換する)。parseIntとNumber()の違いは何ですか?parseInt('12abc')は12を返し、左から右に解析できなくなるまで解析を続けます。Number('12abc')はNaNを返し、文字列全体が有効な数値である必要があります。緩い解析にはparseInt、厳密な変換にはNumber()を使います。📝 演習
- 円の半径を入力として受け取り、面積と円周を計算し、結果を小数点以下2桁に丸めて表示するプログラムを書いてください。
- 数当てゲームを作成してください:プログラムが1から100までのランダムな整数を生成し、ユーザーが推測を入力すると、正解が見つかるまで「大きすぎます」または「小さすぎます」と応答します。
- 基数変換器を作成してください:10進数を入力すると、2進数、8進数、16進数の等価値を同時に表示します。



