Skip to content

Instantly share code, notes, and snippets.

@disktnk
Created July 28, 2012 16:17
Show Gist options
  • Save disktnk/3193889 to your computer and use it in GitHub Desktop.
Save disktnk/3193889 to your computer and use it in GitHub Desktop.
forループにInteger.MAX_VALUE入れた時の変な挙動

川中さんらの「アルゴリズムを学ぼう」のサンプルコードを愚直に写そうと思ったら,初っ端から躓いたので,そのメモ.といっても,本書のサンプルコードは正しい.MacのJava6で起こるけど,WinのJava7では再現しなかった.ちゃんと確かめてはいない.

##ひとまずリスト1-1のサンプルコードを写経

問題文は「aのk乗をmで割った余りを求めよ」で,そのままサンプルを写す.staticなのは,単純にmain関数からお手軽に呼び出したかったからというだけで,深い意味はない.

// aのk乗からmで割ったあまりを求める,本書のリスト1-1ママ
static int powmod(int a, int k, int m) {
    long t = 1;
    for (int i = 0; i < k; ++i) {
        t = (t * a) % m;
    }
    return (int) t;
}

んで,このメソッドを以下のように呼び出すと,正しい答えが出ない.実行するたびに答えが変わる.正しい答えは1787.

// O(n)の実行
int ans = powmod(3, Integer.MAX_VALUE, 10000);
System.out.println("answer: " + ans);

##Why?

どうやら,forループが第2引数のk回分回っていないのが原因らしい.

// aのk乗からmで割ったあまりを求める
static int powmod(int a, int k, int m) {
    long t = 1;
    int c = 0; // forループのカウンター
    for (int i = 0; i < k; ++i) {
        t = (t * a) % m;
        c++;
    }
    // ループがk回実行されていないことの確認
    System.out.println(c);
    return (int) t;
}

上記コードで第2引数kにInteger.MAX_VALUEを入れて実行すると,変数cの値が2147483647 (=2^31-1)となるはずが,そうならない模様.ちなみに正しい挙動をしないのは第2引数kに2147483647を入れたときのみであり,それ以外の数字,たとえば2147483646 (= Integer.MAX_VALUE - 1)とかだと,正しい挙動をする.

##原因

JDK6のバグらしい.すでにstackoverflowにあった.

Interestingly, the javac-produced version uses if_icmpge as an exit condition (>= 2147483647) on an int, which shouldn't make sense (the equal does, but not the greater than). Both look correct, though, so I'd suspect a JVM bug.

Erroneous for-loops in Java? - Stack Overflow

だそうな.JDK7では修正されているというコメントがある.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment