川中さんらの「アルゴリズムを学ぼう」のサンプルコードを愚直に写そうと思ったら,初っ端から躓いたので,そのメモ.といっても,本書のサンプルコードは正しい.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.
だそうな.JDK7では修正されているというコメントがある.