ワンライナーの陥穽。
剰余(n rem m)演算とモジュロ(n mod m)演算はnが負のとき結果が違ってきます。端的に言うとモジュロ演算で結果が負の数になることはありません。(詳細は英語版ウィキペディアのモジュロ演算。)
例を挙げた方がいいか……。
n | -7 | -6 | -5 | -4 | -3 | -2 | -1 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
rem 3 | -1 | 0 | -2 | -1 | 0 | -2 | -1 | 0 | 1 | 2 | 0 | 1 |
mod 3 | 2 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 | 2 | 0 | 1 |
C言語やJavaの%演算子は剰余演算なので、モジュロ演算の方は(必要なら)自分で書くことになります。
public static int mod(int n, int m) { if (m <= 0) { throw new ArithmeticException(); } int rem = n % m; if (n < 0) { return rem + m; } else { return rem; } }
一部ではif文抜きでモジュロ演算する裏技(?)として、
(n % m + m) % m
が紹介されています。が、これは途中で足し算がオーバーフローすると悲惨なことになるので避けましょう。
int m = Integer.MAX_VALUE; System.out.println(mod(10, m)); System.out.println((10 % m + m) % m);
10 -2147483639
一見よさそうに見えて罠が潜んでいる、という話でした。了。