【JavaScript】四則演算と計算の基本|算術演算子・Math・小数計算の注意点まで解説

【JavaScript】四則演算と計算の基本|算術演算子・Math・小数計算の注意点まで解説 JavaScript

JavaScriptで数値の計算を行うには、算術演算子(+, -, *, / など)を使います。加減乗除の基本はもちろん、剰余(%)やべき乗(**)、Mathオブジェクトによる高度な計算、浮動小数点の罠まで理解しておくことで、実務で正確な計算処理が書けるようになります。

この記事では、JavaScriptの計算に関する知識を算術演算子の基本から消費税計算・数値フォーマットなどの実務パターンまで体系的に解説します。

この記事で学べること

  • 算術演算子(+, -, *, /, %, **)の使い方と優先順位
  • 代入演算子(+=, -= など)とインクリメント・デクリメント
  • Mathオブジェクト(round, floor, ceil, random など)
  • 数値の型変換(Number, parseInt, parseFloat)と落とし穴
  • 浮動小数点問題(0.1 + 0.2)の原因と対策
  • 消費税計算・パーセント計算・数値フォーマットなど実務パターン
  • NaN・Infinity・0除算などよくあるミス
スポンサーリンク

算術演算子の一覧と基本

JavaScriptには以下の算術演算子が用意されています。四則演算に加えて、剰余(余り)とべき乗も覚えておきましょう。

演算子 名前 結果
+ 加算(足し算) 10 + 3 13
減算(引き算) 10 – 3 7
* 乗算(掛け算) 10 * 3 30
/ 除算(割り算) 10 / 3 3.3333…
% 剰余(余り) 10 % 3 1
** べき乗 2 ** 3 8

四則演算の基本

最も基本的な加算・減算・乗算・除算の例を見てみましょう。

JavaScript
// 加算(足し算)
console.log(10 + 3);   // 13
console.log(5 + 2.5); // 7.5

// 減算(引き算)
console.log(10 - 3);   // 7
console.log(5 - 8);   // -3(負の数もOK)

// 乗算(掛け算)
console.log(10 * 3);   // 30
console.log(4 * 0.5); // 2

// 除算(割り算)
console.log(10 / 3);   // 3.3333333333333335
console.log(10 / 2);   // 5

ポイント:JavaScriptの除算は整数同士でも小数の結果を返します。他の言語(Java, C など)のように切り捨てにはなりません。整数の結果が必要な場合は Math.floor()Math.trunc() を使います。

剰余演算子(%)

剰余演算子(%)は割り算の余りを返します。偶数・奇数の判定やループ処理でよく使います。

JavaScript
// 剰余(余り)の基本
console.log(10 % 3);  // 1  (10 ÷ 3 = 3 余り 1)
console.log(15 % 5);  // 0  (割り切れる)
console.log(7 % 2);   // 1  (奇数)
console.log(8 % 2);   // 0  (偶数)

// 偶数・奇数の判定に使える
function isEven(num) {
  return num % 2 === 0;
}

console.log(isEven(4));  // true
console.log(isEven(7));  // false

べき乗演算子(**)

べき乗演算子(**)はES2016で追加された演算子で、Math.pow() と同じ計算をより簡潔に書けます。

JavaScript
// べき乗(累乗)
console.log(2 ** 3);   // 8    (2の3乗)
console.log(3 ** 2);   // 9    (3の2乗)
console.log(10 ** 0);  // 1    (何でも0乗は1)
console.log(4 ** 0.5); // 2    (平方根と同じ)

// Math.pow() と同じ結果
console.log(Math.pow(2, 3)); // 8

演算子の優先順位

算術演算子には優先順位があります。数学と同じく、乗算・除算は加算・減算より先に計算されます。

優先順位 演算子 説明
1(高い) ( ) 括弧(最優先)
2 ** べき乗
3 *, /, % 乗算・除算・剰余
4(低い) +, – 加算・減算
JavaScript
// 乗算・除算は加算・減算より先に計算される
console.log(2 + 3 * 4);     // 14(3 * 4 = 12 → 2 + 12 = 14)
console.log((2 + 3) * 4);   // 20(括弧が最優先)

// べき乗は乗算より優先される
console.log(2 * 3 ** 2);     // 18(3 ** 2 = 9 → 2 * 9 = 18)

// 迷ったら括弧を使って明示するのがベスト
const result = (100 - 20) * (1 + 0.1);
console.log(result); // 88(税込み計算の例)

代入演算子(+=, -=, *=, /=, %=, **=)

代入演算子は「計算して代入する」を1行で書ける省略記法です。変数の値を更新する場面で頻繁に使います。

演算子 意味 等価な式
x += y 加算して代入 x = x + y
x -= y 減算して代入 x = x – y
x *= y 乗算して代入 x = x * y
x /= y 除算して代入 x = x / y
x %= y 剰余を代入 x = x % y
x **= y べき乗して代入 x = x ** y
JavaScript
let score = 100;

score += 10;  // score = 100 + 10 → 110
score -= 20;  // score = 110 - 20 → 90
score *= 2;   // score = 90 * 2  → 180
score /= 3;   // score = 180 / 3 → 60
score %= 7;   // score = 60 % 7  → 4
score **= 3;  // score = 4 ** 3  → 64

console.log(score); // 64

インクリメント・デクリメント(++, –)

インクリメント(++)は値を1増やし、デクリメント(–)は値を1減らします。前置と後置で式の中での評価タイミングが異なります。

JavaScript
let a = 5;
let b = 5;

// 後置(postfix): 現在の値を返してからインクリメント
console.log(a++); // 5(先に5を返し、その後 a が 6 になる)
console.log(a);   // 6

// 前置(prefix): インクリメントしてから値を返す
console.log(++b); // 6(先に b が 6 になり、6を返す)
console.log(b);   // 6

// デクリメントも同様
let c = 10;
c--;
console.log(c); // 9

// forループでよく使われる
for (let i = 0; i < 3; i++) {
  console.log(i); // 0, 1, 2
}

注意:前置と後置の違いは「式の中で使うとき」に影響します。単独で i++ と書く場合(forループなど)は前置・後置どちらでも結果は同じです。

Mathオブジェクトを使った計算

JavaScriptのMathオブジェクトには、四捨五入・切り捨て・乱数生成など、算術演算子だけでは実現できない数学的な計算メソッドが多数用意されています。

四捨五入・切り捨て・切り上げ

小数点以下の処理は実務で最もよく使うMathメソッドです。

メソッド 動作 2.7 2.3 -2.7
Math.round() 四捨五入 3 2 -3
Math.floor() 切り捨て(小さい方へ) 2 2 -3
Math.ceil() 切り上げ(大きい方へ) 3 3 -2
Math.trunc() 整数部分のみ(0方向へ) 2 2 -2
JavaScript
// 四捨五入
console.log(Math.round(2.7));  // 3
console.log(Math.round(2.3));  // 2
console.log(Math.round(2.5));  // 3(.5は切り上げ)

// 切り捨て(負の数に注意)
console.log(Math.floor(2.9));   // 2
console.log(Math.floor(-2.1));  // -3(小さい方へ丸める)

// 切り上げ
console.log(Math.ceil(2.1));   // 3
console.log(Math.ceil(-2.9));  // -2(大きい方へ丸める)

// 整数部分のみ(0方向)
console.log(Math.trunc(2.9));   // 2
console.log(Math.trunc(-2.9));  // -2

最大値・最小値(Math.max / Math.min)

複数の値から最大値・最小値を取得します。配列に対して使う場合はスプレッド構文を組み合わせます。

JavaScript
// 引数から最大値・最小値を取得
console.log(Math.max(10, 5, 20, 3));  // 20
console.log(Math.min(10, 5, 20, 3));  // 3

// 配列の最大値・最小値(スプレッド構文)
const scores = [85, 92, 78, 95, 60];
console.log(Math.max(...scores)); // 95
console.log(Math.min(...scores)); // 60

乱数生成(Math.random)

Math.random()0以上1未満 のランダムな小数を返します。整数の乱数が必要な場合は Math.floor() と組み合わせます。

JavaScript
// 0以上1未満のランダムな小数
console.log(Math.random()); // 例: 0.7234...

// 0〜9 の整数
console.log(Math.floor(Math.random() * 10));

// 1〜10 の整数
console.log(Math.floor(Math.random() * 10) + 1);

// min〜max の整数を生成する汎用関数
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

console.log(getRandomInt(1, 100)); // 1〜100のランダムな整数

その他の便利なMathメソッド

JavaScript
// 絶対値
console.log(Math.abs(-5));   // 5
console.log(Math.abs(5));    // 5

// 平方根
console.log(Math.sqrt(9));   // 3
console.log(Math.sqrt(2));   // 1.4142135623730951

// べき乗(** 演算子と同じ)
console.log(Math.pow(2, 10)); // 1024

// 円周率
console.log(Math.PI); // 3.141592653589793

// 円の面積を求める
const radius = 5;
const area = Math.PI * radius ** 2;
console.log(area); // 78.53981633974483

数値の型変換

JavaScriptでは文字列を数値に変換する場面が頻繁にあります。Number()parseInt()parseFloat() の3つの方法と、それぞれの違いを理解しておきましょう。

メソッド 動作 "123" "12.5" "12px" ""
Number() 厳密な変換 123 12.5 NaN 0
parseInt() 整数として解析 123 12 12 NaN
parseFloat() 小数として解析 123 12.5 12 NaN
JavaScript
// Number(): 厳密な変換(数値以外が含まれるとNaN)
console.log(Number('123'));    // 123
console.log(Number('12.5'));   // 12.5
console.log(Number('12px'));   // NaN(数値以外を含む)
console.log(Number(''));      // 0(空文字は0)
console.log(Number(true));    // 1
console.log(Number(false));   // 0
console.log(Number(null));    // 0

// parseInt(): 先頭から整数として解析
console.log(parseInt('12px'));    // 12(先頭の数値部分を取得)
console.log(parseInt('12.9'));    // 12(小数点以下は切り捨て)
console.log(parseInt('abc'));     // NaN
console.log(parseInt('0xFF', 16)); // 255(16進数)

// parseFloat(): 先頭から小数として解析
console.log(parseFloat('12.5px')); // 12.5
console.log(parseFloat('3.14'));   // 3.14

文字列 + 数値の落とし穴

JavaScriptの + 演算子は、片方が文字列だと文字列結合になります。これは初心者が最もハマりやすいポイントです。

JavaScript
// 文字列 + 数値 => 文字列結合(足し算にならない!)
console.log('5' + 3);    // "53"(文字列結合)
console.log('10' + 20);  // "1020"(文字列結合)

// -, *, / は文字列を自動で数値に変換する
console.log('5' - 3);    // 2(数値として計算)
console.log('10' * 2);   // 20(数値として計算)
console.log('20' / 4);   // 5(数値として計算)

注意:+ 演算子だけが文字列結合と加算の両方の意味を持ちます。フォーム入力値(常に文字列)を計算に使う場合は、必ず Number()parseInt() で数値に変換してから計算しましょう。

単項+演算子による変換

変数の前に + を付けると Number() と同じ効果で数値に変換できます。簡潔に書けるため実務でもよく使われます。

JavaScript
const input = '42';

// 単項+演算子で数値に変換
console.log(+input);       // 42(数値)
console.log(+'3.14');     // 3.14
console.log(+true);        // 1
console.log(+'abc');      // NaN

// 計算時の活用例
const price = '1000';
const tax = '0.1';
console.log(+price * (1 + +tax)); // 1100

小数計算の注意点(浮動小数点問題)

JavaScriptで小数を扱う際に必ず知っておくべき重要な問題があります。それが浮動小数点問題です。

0.1 + 0.2 !== 0.3 の真実

JavaScriptの数値は内部的にIEEE 754 倍精度浮動小数点数(64ビット)で表現されています。10進数の小数(0.1 や 0.2)は2進数では無限小数になるため、微小な誤差が生じます。

JavaScript
console.log(0.1 + 0.2); // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false!

// 他にも誤差が出る例
console.log(0.1 + 0.7); // 0.7999999999999999
console.log(1.1 + 2.2); // 3.3000000000000003
実行結果
0.30000000000000004
false
0.7999999999999999
3.3000000000000003

重要:これはJavaScript固有の問題ではなく、IEEE 754浮動小数点数を使うほぼすべてのプログラミング言語(Python, Java, C, Ruby など)で発生します。

対策1:toFixed() で丸める

toFixed() は指定した桁数で数値を丸めて文字列として返します。表示目的には最も手軽な方法です。

JavaScript
const result = 0.1 + 0.2;

// toFixed() は文字列を返す
console.log(result.toFixed(1));  // "0.3"(文字列)
console.log(result.toFixed(2));  // "0.30"

// 数値として使いたい場合は Number() で変換
console.log(Number(result.toFixed(1))); // 0.3(数値)

// 金額表示に便利
const price = 19.999;
console.log(price.toFixed(2)); // "20.00"

対策2:整数化して計算する

金額計算など正確さが求められる場面では、いったん整数に変換してから計算し、最後に戻す方法が確実です。

JavaScript
// NG: 小数のまま計算すると誤差が出る
console.log(0.1 + 0.2); // 0.30000000000000004

// OK: 整数にしてから計算
console.log((1 + 2) / 10); // 0.3(正確)

// 金額計算の例(円単位で計算)
function addPrice(a, b) {
  // 小数を整数に変換して計算し、最後に戻す
  return (Math.round(a * 100) + Math.round(b * 100)) / 100;
}

console.log(addPrice(0.1, 0.2)); // 0.3(正確)

ポイント:ECMAScript提案中の Decimal 型が将来的に追加される可能性がありますが、現時点では整数化して計算する方法が最も安全です。金額計算が多いプロジェクトでは decimal.js などのライブラリの導入も検討しましょう。

実務でよく使う計算パターン

ここからは、実際のWeb開発で頻繁に登場する計算パターンを紹介します。コピペしてすぐ使えるコードを中心にまとめました。

消費税計算

EC サイトや見積もりシステムで必須の消費税計算です。浮動小数点問題を考慮した安全な実装を紹介します。

JavaScript
// 消費税計算(税率10%)
function calcTax(price, taxRate = 0.1) {
  const tax = Math.floor(price * taxRate);
  return {
    price,
    tax,
    total: price + tax
  };
}

console.log(calcTax(1980));
// { price: 1980, tax: 198, total: 2178 }

// 軽減税率8%の場合
console.log(calcTax(1980, 0.08));
// { price: 1980, tax: 158, total: 2138 }

割合・パーセント計算

JavaScript
// パーセント計算
function calcPercent(part, total) {
  return Math.round((part / total) * 100 * 10) / 10;
}

console.log(calcPercent(75, 200));  // 37.5
console.log(calcPercent(1, 3));    // 33.3

// 割引計算
function discount(price, percent) {
  return Math.floor(price * (1 - percent / 100));
}

console.log(discount(3000, 20)); // 2400(20%オフ)
console.log(discount(3000, 15)); // 2550(15%オフ)

乱数で範囲指定した整数を生成

JavaScript
// min以上max以下のランダムな整数
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

// サイコロ(1〜6)
console.log(randomInt(1, 6));

// パスワード生成風(ランダムな4桁)
console.log(randomInt(1000, 9999));

// 配列からランダムに1つ選ぶ
const fruits = ['りんご', 'みかん', 'ぶどう', 'バナナ'];
const index = randomInt(0, fruits.length - 1);
console.log(fruits[index]);

カンマ区切りの数値フォーマット(toLocaleString)

大きな数値を読みやすくカンマ区切りにするには toLocaleString() が最も簡単です。

JavaScript
// toLocaleString() でカンマ区切り
console.log((1234567).toLocaleString()); // "1,234,567"

// 通貨フォーマット(日本円)
const yen = (29800).toLocaleString('ja-JP', {
  style: 'currency',
  currency: 'JPY'
});
console.log(yen); // "¥29,800"

// 小数点付き通貨(米ドル)
const usd = (1234.5).toLocaleString('en-US', {
  style: 'currency',
  currency: 'USD'
});
console.log(usd); // "$1,234.50"

// パーセント表示
const rate = (0.156).toLocaleString('ja-JP', {
  style: 'percent',
  minimumFractionDigits: 1
});
console.log(rate); // "15.6%"

よくあるミスと注意点

JavaScript の計算処理で遭遇しやすい落とし穴をまとめました。デバッグ時間を大幅に節約できます。

NaN(Not a Number)の扱い

NaN は「数値ではない」ことを表す特殊な値です。数値として不正な計算を行うと返されます。

JavaScript
// NaN が発生するケース
console.log(0 / 0);             // NaN
console.log(Number('abc'));     // NaN
console.log(parseInt('hello')); // NaN
console.log(Math.sqrt(-1));     // NaN

// NaN の厄介な性質: 自分自身と等しくない
console.log(NaN === NaN);  // false!
console.log(NaN == NaN);   // false!

// NaN の判定には isNaN() または Number.isNaN() を使う
console.log(isNaN(NaN));            // true
console.log(isNaN('abc'));          // true(暗黙の型変換あり)
console.log(Number.isNaN(NaN));     // true
console.log(Number.isNaN('abc')); // false(より厳密)

// NaN が伝播する(NaN を含む計算結果はすべて NaN)
console.log(NaN + 5);   // NaN
console.log(NaN * 10);  // NaN

ベストプラクティス:NaN チェックには Number.isNaN() を使いましょう。グローバルの isNaN() は引数を暗黙的に数値変換するため、isNaN("abc") が true を返す等の意図しない挙動があります。

Infinity と -Infinity

JavaScript
// 0以外の数値を0で割るとInfinity
console.log(10 / 0);   // Infinity
console.log(-10 / 0);  // -Infinity
console.log(0 / 0);    // NaN(0÷0は不定形)

// Infinity の性質
console.log(Infinity + 1);        // Infinity
console.log(Infinity * 2);        // Infinity
console.log(Infinity - Infinity); // NaN
console.log(1 / Infinity);        // 0

// 有限数チェック
console.log(isFinite(100));       // true
console.log(isFinite(Infinity));  // false
console.log(isFinite(NaN));       // false

型変換による意図しない結果

JavaScriptの暗黙的な型変換は時として驚くような結果を生みます。計算処理では明示的に型変換する習慣をつけましょう。

JavaScript
// 意図しない型変換の例
console.log('5' + 3);       // "53"(文字列結合)
console.log('5' - 3);       // 2(数値の引き算)
console.log(true + 1);      // 2(true => 1)
console.log(false + 1);     // 1(false => 0)
console.log(null + 5);      // 5(null => 0)
console.log(undefined + 5); // NaN(undefined => NaN)
console.log('' + 0);       // "0"(文字列結合)
console.log('' - 0);       // 0(空文字 => 0)

対策:フォーム入力やAPIレスポンスの値を計算に使う前に、必ず Number() で明示的に変換し、Number.isNaN() でチェックしましょう。暗黙の型変換に頼らない安全なコードを書く習慣が重要です。

まとめ

JavaScriptの計算処理について、算術演算子の基本からMathオブジェクト、型変換、浮動小数点問題、実務パターンまで解説しました。最後に演算子一覧表で全体を振り返りましょう。

カテゴリ 演算子・メソッド 用途
算術演算子 +, -, *, /, %, ** 四則演算・剰余・べき乗
代入演算子 +=, -=, *=, /=, %=, **= 計算して代入
増減 ++, — インクリメント・デクリメント
丸め処理 Math.round / floor / ceil / trunc 四捨五入・切り捨て・切り上げ
最大・最小 Math.max / Math.min 最大値・最小値
乱数 Math.random() 0以上1未満の乱数
型変換 Number / parseInt / parseFloat 文字列→数値変換
数値フォーマット toFixed / toLocaleString 小数桁数指定・カンマ区切り

この記事のポイント

  • 算術演算子は優先順位を理解し、迷ったら括弧を使う
  • 代入演算子(+=など)で変数の更新をシンプルに書ける
  • Mathオブジェクトで四捨五入・乱数・絶対値などの計算が可能
  • 型変換は明示的に行い、「文字列+数値」の罠に注意する
  • 浮動小数点問題は整数化して計算する方法で回避する
  • NaN・Infinityの挙動を理解し、Number.isNaN() でチェックする

JavaScriptの計算処理は基本的な算術演算子だけでなく、Mathオブジェクトや型変換、浮動小数点の挙動まで理解することで、バグのない正確な計算コードが書けるようになります。特に金額計算やユーザー入力値を扱う場面では、型変換と浮動小数点問題を常に意識しましょう。