Rainbow Engine

IT技術を分かりやすく簡潔にまとめることによる学習の効率化、また日常の気付きを記録に残すことを目指します。

Java

int型のオーバーフロー(桁あふれ)とは?実際の発生パターンと併せてご紹介

投稿日:2021年6月26日 更新日:

 

<目次>

(1) int型のオーバーフロー(桁あふれ)とは?実際の発生パターンと併せてご紹介
 (1-1) int型のオーバーフローとは?
 (1-2) int型のオーバーフローが発生するとどうなるの?
 (1-3) int型のオーバーフローの発生サンプル

(1) int型のオーバーフロー(桁あふれ)とは?実際の発生パターンと併せてご紹介

(1-1) int型のオーバーフローとは?

int型のオーバーフロー(桁あふれ)とは、int型の変数にintで保持できる最大値(符号付き32bitの場合、+2,147,483,647~-2,147,483,648の範囲)を超える値を格納しようとした際に発生します。

多くのプログラミング言語において、通常int型の値には決められたビット数のメモリが割り当てられます。例えば、32bitのinteger型が確保した猟奇の場合、次の範囲の数値を保持できます。
 
・符号あり32bit(int)
■10進数 ■2進数 ■16進数
2,147,483,647
= pow(2,31) – 1
01111111 11111111 11111111 11111111 0x7FFFFFFF
-2,147,483,648
= pow(2,31)
10000000 00000000 00000000 00000000 0x80000000
・符号なし32bit(unsigned int)
■10進数 ■2進数 ■16進数
0
= pow(2,0) – 1
00000000 00000000 00000000 00000000 0x00000000
4,294,967,295
= pow(2,32) -1
11111111 11111111 11111111 11111111 0xFFFFFFFF

目次にもどる

(1-2) int型のオーバーフローが発生するとどうなるの?

以下はJavaの例ですが、両端(最大=2147483647と最小=-2147483648)の数字に対して、最大は更に+1、最小は更に-1するとどうなるか?をチェックしていますが、結果的には逆側の最大値に反転しています。

・MAX+1 = 2147483647+1 = -2147483648
・MIN-1 = -2147483648-1 = 2147483647
 
public class ITxxxx_OverflowExample {
    public static void main(String args[]){

        //# 符号付き32bitのint型の最大+1
        int test1 = 2147483647;
        System.out.println("TEST_1 = "+ (test1 + 0));
        System.out.println("TEST_2 = "+ (test1 + 1));

        //# 符号付き32bitのint型の最小ー1
        int test2 = -2147483648;
        System.out.println("TEST_3 = "+ (test2 - 0));
        System.out.println("TEST_4 = "+ (test2 - 1));
    }
}

 

(図121)

この結果として、オーバーフローにより意図せず符号が反転してしまい、配列などでマイナスのインデックスが指定されてしまい、「ArrayIndexOutOfBoundsException」等の例外につながる、といった問題が想定されます。
 
また、この例はJavaですが他にもC#やC++など多くのプログラミング言語では同様の挙動をしています(Python等の例外もあり)。
 

(1-3) int型のオーバーフローの発生サンプル

実際に数値解析等のアルゴリズムにおいても、オーバーフローが発生する可能性があります。

(例)バイナリサーチ
こちらのバイナリサーチの紹介記事に掲載しているプログラムですが、範囲の中央(mid)を求める所で次のように記載しています。
 
//①
int mid = (lo + hi) / 2;

一見すると問題ないように見えますが、この計算は探索対象の配列が非常に大きい場合に「lo + hi」が「int型の最大」である「2147483647」を超えた場合にオーバーフローが発生する可能性があるため、正しくは次のように記載する必要があります。

//②
int mid = lo + (hi – lo) / 2;

この②は一見すると①と別の式に見えますが、実際に式変換すると同じ式である事が分かります。

② = lo + (hi – lo) / 2
= (2*lo + (hi – lo)) / 2
= (lo + hi) / 2
= ①

 

目次にもどる

Adsense審査用広告コード


Adsense審査用広告コード


-Java

執筆者:


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Twitter APIライブラリ(Twitter4j)を用いてDMを送信する方法

<目次> (1) Twitter APIライブラリ(Twitter4j)を用いてDMを送信する方法  (1-1) 構文  (1-2) 開発者用アカウントの設定変更  (1-3) 認証トークンの再生成 …

Javaで正規表現の使い方をご紹介+サンプルプログラム付き

<目次> (1) Javaで正規表現の使い方をご紹介  (1-1) 正規表現とは?  (1-2) Javaでの正規表現の使い方  (1-3) サンプルプログラム (1) Javaで正規表現の使い方をご …

Javaのフォーム認証でログインを行うと数回で固まってしまう事象の対処記録

<目次> (1) Javaのフォーム認証でログインを行うと数回で固まってしまう事象の対処記録  (1-1) 発生事象・エラーメッセージ  (1-2) 原因  (1-3) 対策 (1) Javaのフォー …

JavaでJSON配列から値を抽出する方法+郵便番号検索APIのサンプルプログラムも紹介

(0)目次&概説 (1) 記事の目的  (1-1) 目的  (1-2) 前提条件 (2) JSON配列から値抽出する方法  (2-1) JSON配列のデータの構造例  (2-2) JSON配列のデータ …

CentOS7にEclipseをインストールする手順

<目次> (1) CentOS7にEclipseをインストールする手順  (1-1) JDKのインストール  (1-2) Eclipse資源のダウンロード  (1-3) Eclipseのインストール …

  • English (United States)
  • 日本語
Top