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

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

関連記事

no image

jarファイル実行で「java.lang.ClassNotFoundException: com.sun.prism.es2.X11GLFactory」が出る原因と対策

  <目次> (1) jarファイル実行で「java.lang.ClassNotFoundException: com.sun.prism.es2.X11GLFactory」が出る原因と対策 …

JavaのBigDecimalの使い方+初期化・四則演算・余り・累乗等の主要用途も紹介

<目的> (1) JavaのBigDecimalの使い方+初期化や四則演算・桁数設定等の主要用途も紹介  (1-1) 宣言の方法  (1-2) 代表的な用途(足し算・引き算・掛け算・割り算)  (1- …

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

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

JVMの基本アーキテクチャと各サブシステム等の概要説明について

(0)目次&概説 (1) 記事の目的 (2) Javaのアーキテクチャ概要・概観 (3) JVMのアーキテクチャ概要  (3-1) JVMの概観  (3-2) JVMの主要サブシステム1:Class …

no image

HTMLで<a>要素のリンクを中央寄せする方法

<目次> (1) HTMLで<a>要素のリンクを中央寄せする方法  (1-1) 構文  (1-2) サンプルプログラム  (1-3) サンプルプログラム実行結果 (1) HTMLで< …

  • English (United States)
  • 日本語
Top