404 Not Found

404 Not Found


nginx

JavaScriptの数値とMath

JavaScriptには数値型が1つだけあります:Numberです。整数でも小数でも、すべてNumberです。これはintやfloatを区別するJavaやCとは異なります。シンプルですが、いくつかの注意点があります。

Number型

JavaScriptでは、整数も浮動小数点数もNumber型です。整数専用の型はありません。

HTML
<script>
let a = 42;        // これはNumber
let b = 3.14;      // これもNumber
typeof a;          // "number"
typeof b;          // "number"
</script>

数値は他の形式でも記述できます:

HTML
<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のもっとも皮肉な設計選択の一つです。

HTML
<script>
typeof NaN;          // "number"  ← そうです、実は数値です
NaN === NaN;         // false     ← 自分自身とも等しくない!
Number.isNaN(NaN);   // true      ← このメソッドでNaNをチェックする
</script>

NaNはいつ出現するのでしょう?数値でないもので計算をしようとしたときです:

HTML
<script>
parseInt('abc');    // NaN
'hello' * 5;       // NaN
Math.sqrt(-1);     // NaN
</script>

Infinityは正の無限大を表し、ゼロで割ったときに現れます:

HTML
<script>
1 / 0;             // Infinity
-1 / 0;            // -Infinity
typeof Infinity;   // "number"
</script>

💪 NaNかどうかをチェックするには、===を絶対に使わずNumber.isNaN()を使いましょう。NaN === NaNfalseなので、これは無数の開発者が引っかかってきた落とし穴です。

浮動小数点の精度

これはJavaScriptのもっとも有名な癖です:0.1 + 0.2 !== 0.3

HTML
<script>
0.1 + 0.2;          // 0.30000000000000004
0.1 + 0.2 === 0.3;  // false
</script>

理由は、コンピュータが浮動小数点数をバイナリで保存する方法に関係しています。値0.1はバイナリでは循環小数となり、保存時に精度が失われます。これはJavaScriptに特有の問題ではなく、IEEE 754標準を使用するすべての言語に存在します。

対策:toFixed()でフォーマットするか、計算前にスケールアップします:

HTML
<script>
(0.1 + 0.2).toFixed(2);   // "0.30"
(0.1 * 100 + 0.2 * 100) / 100;  // 0.3
</script>

実例:精度問題デモ

HTML
<!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メソッド

HTML
<!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桁にフォーマットし、文字列を返します:

HTML
<script>
let price = 9.9;
price.toFixed(2);    // "9.90"  ← 注意:文字列を返す
+(9.9).toFixed(2);   // 9.9     ← +で数値に戻す
</script>
⚠️ toFixedは文字列を返します!その後さらに計算する必要がある場合は、数値に変換し直しましょう。

toString() — 基数変換

数値メソッドtoString(radix)は数値を指定された基数の文字列に変換します:

HTML
<script>
(255).toString(16);   // "ff"  16進数
(255).toString(2);    // "11111111"  2進数
(255).toString(8);    // "377"  8進数
(100).toString();     // "100"  10進数(デフォルト)
</script>

実例:基数変換

HTML
<!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(未満)のランダムな浮動小数点数を返します。実際には、特定の範囲内のランダムな整数が必要になることが多いです:

HTML
<script>
// minからmax(両端含む)までのランダムな整数を生成
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
</script>

実例:乱数デモ

HTML
<!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()を使いましょう。


📖 まとめ

  1. JavaScriptにはNumber型が1つだけで、整数も小数もNumber
  2. NaNはどの値とも等しくない(自分自身も含む)。検出にはNumber.isNaN()を使う
  3. 0.1 + 0.2 !== 0.3は精度の問題で、toFixed()やスケールアップ/ダウンで対策する
  4. Math.floorは切り捨て、Math.ceilは切り上げ、Math.roundは四捨五入
  5. ランダムな整数の公式:Math.floor(Math.random() * (max - min + 1)) + min
  6. toFixed()は文字列を返す — さらに計算する場合は数値に戻す

❓ よくある質問

Q Math.round(2.5)Math.round(-2.5)はそれぞれいくつですか?
A Math.round(2.5)3Math.round(-2.5)-2です。小数部分がちょうど.5のとき、JavaScriptは正の無限大の方向に丸めるため、正の数と負の数の両方がゼロに近い方に丸められます。
Q 値が有効な有限数かどうかをどうチェックしますか?
A Number.isFinite(value)を使います。NaNInfinity-Infinityを除外し、数値型以外も拒否します。グローバルのisFinite()も使えますが、型チェックをしません(先に型変換する)。
Q parseIntNumber()の違いは何ですか?
A parseInt('12abc')12を返し、左から右に解析できなくなるまで解析を続けます。Number('12abc')NaNを返し、文字列全体が有効な数値である必要があります。緩い解析にはparseInt、厳密な変換にはNumber()を使います。

📝 演習

  1. 円の半径を入力として受け取り、面積と円周を計算し、結果を小数点以下2桁に丸めて表示するプログラムを書いてください。
  2. 数当てゲームを作成してください:プログラムが1から100までのランダムな整数を生成し、ユーザーが推測を入力すると、正解が見つかるまで「大きすぎます」または「小さすぎます」と応答します。
  3. 基数変換器を作成してください:10進数を入力すると、2進数、8進数、16進数の等価値を同時に表示します。
100%