LoginSignup
12
8

More than 5 years have passed since last update.

整数のオーバーフローで忘れがちなケース

Last updated at Posted at 2018-05-08

プログラマの方は、演算時には、オーバーフローに関しては、
常に気を使っていると思いますが、
それでも忘れがちなケースを簡単にまとめます。

この記事は、以下の内容からピックアップした外伝的な内容です。

1. 話しを単純にするための前提条件

話しを単純にするために、32bitの符号付き整数型を想定します。
今回の内容に関しては、精度が決まっている符号付きの整数型であれば、
他のサイズでも該当するはずです。

Java, C#, C/C++では、
int、Int32, int32などを思いうかべると良いかと思います。
(C/C++では、int型が32ビットの処理系を想定。)

2. 乗算(掛け算)での忘れがちなオーバーフロー

大きな数値同士の掛け算とかは、オーバーフローしやすいのは、
すぐイメージできると思うので、本題ではありません。

本題としては、以下のようなケースです。

  • C#
int a = Int32.MinValue;
int b = -1;

int answer = a * b;
  • Java
int a = Integer.MIN_VALUE;
int b = -1;

int answer = a * b;
  • C/C++
int a = INT_MIN;
int b = -1;

int answer = a * b;

aには、-2147483648が入っていますが、
-1を掛けると、32ビットの符号付き整数で表現可能な2147483647を超えます。
手元の環境では、いずれもanswer変数の結果は、-2147483648になりました。
C#に関しては、checkedにした場合は、OverFlowExceptionが発生します。

ビルドやコンパイル時点で、値が評価できる場合は、
その時点で、オーバーフローを検出する場合もあります。

3. 除算(割り算)での忘れがちなオーバーフロー

整数の割り算では、オーバーフローは発生しないと、
勘違いされているケースもありますが、ちゃんと(?!)オーバーフローする場合があります。

  • C#
int a = Int32.MinValue;
int b = -1;

int answer = a / b;
  • Java
int a = Integer.MIN_VALUE;
int b = -1;

int answer = a / b;
  • C/C++
int a = INT_MIN;
int b = -1;

int answer = a / b;

掛け算の場合と同様ですが、
-1で割ると、-1を掛けるとの同じことなので、
32ビットの符号付き整数で表現可能な2147483647を超えます。
手元の環境では、Javaでは、answer変数の結果は、-2147483648になりました。
C++では、整数オーバーフローの例外が発生しました。
C#に関しては、checkedかどうかにかかわらず、OverFlowExceptionが発生します。

3. まとめ

  • -1を掛けると符号反転するとは限らない(オーバーフローするかもね)。
  • 整数の割り算もオーバーフローする場合がある。
  • 整数の割り算のオーバーフローの場合は、言語・環境でクセがある。
12
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
8