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

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

関連記事

Javaでファイルへの書き込みする方法の基礎(追記・上書き、改行の方法等)

<目次> (1) Javaでファイルへの書き込みする方法の基礎(追記・上書き、改行の方法等)  (1-1) STEP1:FileWriterクラスのインスタンス化  (1-2) STEP2:ファイルへ …

Spring Bootでpom.xmlに「Unknown error」が出た時の対処方法について

  <目次> (1) Spring Bootでpom.xmlに「Unknown error」が出た時の対処方法について  (1-1) 発生状況  (1-2) 原因  (1-3) 対処法①(非 …

JSP/Servletで画面毎のアクセスカウンターを作成してみた(パート1:仕様説明編)

(0)目次&概説 (1) 仕様について  (1-1) アーキテクチャ(アプリ/DB)  (1-2) アプリの仕様概要  (1-3) データベースの仕様概要 (2) ソースコード (3) エラー対応 ( …

Javaの継承やオーバーライドとは?特徴の解説とサンプルプログラムの紹介

(0)目次&概説 (1) 継承/Inherit  (1-1) 継承とは?  (1-2) 継承の特徴  (1-3) 継承のサンプルコード   (1-3-1) Carクラス   (1-3-2) Truck …

TwitterAPIを使ってフォロワーの一覧を取得する方法(Twitter4jライブラリ)

<目次> (1) TwitterAPIを使ってフォロワーの一覧を取得する方法(Twitter4jライブラリ)  (1-1) 構文  (1-2) サンプルプログラム (1) TwitterAPIを使って …

  • English (United States)
  • 日本語
Top