C++の割り算の切り捨てについて

AI実装検定のご案内

C++における割り算は、一見シンプルに見えますが、整数型か浮動小数点型か負の数を含むかによって挙動が大きく変わります。

特に「切り捨て」という言葉は文脈によって意味が異なるため、正確な理解が不可欠です。

本記事では、C++11以降の仕様を前提に、整数除算の切り捨て動作を中心に、実例と注意点を交えて詳しく解説します。

目次

割り算の結果は「型」で決まる

C++の / 演算子は、オペランドの型によって挙動が決まります。

整数型どうしの割り算(整数除算)

int a = 7 / 3;
std::cout << a; // 2
  • 小数点以下は保持されず、整数が返る
  • これを 整数除算 と呼ぶ

浮動小数点型を含む割り算(実数除算)

double b = 7 / 3.0;
std::cout << b; // 2.33333...
  • 少なくとも一方が doublefloat の場合、実数除算になる

重要なポイント

  • int / int → 整数除算
  • int / doubledouble / int → 実数除算

C++11以降の整数除算は「0方向への切り捨て」

C++11以降では、整数除算の結果は 0に向かって切り捨てる(truncation toward zero) と明確に規定されています。

結果
7 / 32
-7 / 3-2
7 / -3-2
-7 / -32
std::cout << -7 / 3; // -2

これは数学でいう floor(下方丸め) とは異なります。

数学的な floor との違いに注意

数学の floor は「負の無限大方向への丸め」です。

#include <cmath>

std::cout << std::floor(-7.0 / 3.0); // -3

比較すると以下のようになります。

処理結果
C++の整数除算-2
floor(-7/3)-3

ポイント

  • C++の整数除算:0方向への切り捨て(trunc)
  • std::floor:下方丸め(数学的定義)

「切り捨て」という日本語が両者で混同されやすいため、0方向(trunc)floor(下方丸め) を意識的に区別すると安全です。

型変換のタイミングによる典型的なミス

よくある誤解

double x = 7 / 3;
std::cout << x; // 2.0

これは 整数除算が先に行われている ため、結果は 2.0 になります。

正しい書き方

double x = 7.0 / 3;
// または
double x = static_cast<double>(7) / 3;

原則

  • 型変換は「割り算の前」に行う

明示的に丸めたい場合の方法

下方丸め(floor)

int a = static_cast<int>(std::floor(7.0 / 3.0)); // 2

上方丸め(ceil)

int b = static_cast<int>(std::ceil(7.0 / 3.0)); // 3

四捨五入(round)

int c = static_cast<int>(std::round(7.0 / 3.0)); // 2

競技プログラミングで頻出の「切り上げ除算」

正の整数に限定する場合、次の式は非常によく使われます。

(a + b - 1) / b

int a = 7, b = 3;
int result = (a + b - 1) / b; // 3

前提条件(重要)

  • a >= 0
  • b > 0
  • a + b - 1オーバーフローしない型であること

大きな数を扱う場合は long long を使うのが安全です。

負の数を含む「数学的 floor 除算」を実装する例

Python の // と同等の挙動(下方丸め)を C++ で再現する例です。

int floor_div(int a, int b) {
    // 前提:b != 0
    int q = a / b;
    int r = a % b;
    if (r != 0 && ((r > 0) != (b > 0))) {
        q--;
    }
    return q;
}
  • C++の /% は 0方向基準
  • 余りの符号と除数の符号を見て補正する

%(剰余)との関係(C++11以降)

C++11以降、次の関係が常に成り立ちます(※ b != 0、オーバーフローしない前提)。

a == (a / b) * b + (a % b)

また、剰余 % の符号は 割られる側(a)の符号に従います。

-7 % 3 == -1

注意すべき未定義・例外ケース

  • b == 0 の除算・剰余 → 未定義動作
  • INT_MIN / -1 → 表現不能(未定義または例外的扱い)

これらは実務・低レイヤ処理では特に注意が必要です。

まとめ

  • C++11以降の整数除算は 0方向への切り捨て
  • 負の数では数学的 floor と結果が異なる
  • 型変換は割り算の前に行う
  • 切り上げ・切り捨ては 意図を明示したコードを書く
  • 境界条件(0除算・オーバーフロー)を常に意識する

以上、C++の割り算の切り捨てについてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次