Я думаю, что это станет понятнее, если вы немного реорганизуете код и сохраните каждое выражение в своей собственной строке.
Значение переменной pos
и MODULO
может быть оба из диапазона -2147483648 и 2147483647
Обратите внимание, что именно: Integer.MAX_VALUE
== 2147483647
. Принимая краевой случай (pos
и MODULO
как можно больше), является хорошим примером:
public static void main(String[] args) {
System.out.println("result: "
+ normalize(Integer.MAX_VALUE-1, Integer.MAX_VALUE));
System.out.println();
System.out.println("result: "
+ normalizeWithoutLongCast(Integer.MAX_VALUE-1, Integer.MAX_VALUE));
}
static int normalize(int pos, int MODULO) {
System.out.println("normalize()");
long mod = pos % MODULO;
System.out.println("mod: "+mod);
long sum = mod + MODULO; // this is where the overflow can occur
System.out.println("sum: "+sum);
return (int) (sum % MODULO);
}
static int normalizeWithoutLongCast(int pos, int MODULO) {
System.out.println("normalizeWithoutLongCast()");
int mod = pos % MODULO;
System.out.println("mod: "+mod);
int sum = mod + MODULO; // this is where the overflow can occur
System.out.println("sum: "+sum);
return (int) (sum % MODULO);
}
Выход:
normalize()
mod: 2147483646
sum: 4294967293
result: 2147483646
normalizeWithoutLongCast()
mod: 2147483646
sum: -3
result: -3
Итак, как вы можете видеть, эта проблема возникает именно в sum = mod + MODULO;
шаге.
MODULO
Как может быть примерно Integer.MAX_VALUE
, это будет означать, добавив, как мало, как 1
к нему будет возвращать значение больше, чем целое число (целое число от переполнения).
Как, на предыдущем этапе (mod = pos2 % MODULO
), у вас есть mod
может быть 1
, может произойти переполнение.
Кастинг до long
позволит получить сумму, не опасаясь переполнения. Конечно, бросок будет проблемой, если мы хотим, чтобы результат был int
.
К счастью, это не проблема здесь, потому что значение последнего выражения (sum % MODULO
) находится в пределах 0
и MODULO
. И так как MODULO
может быть не более Integer.MAX_VALUE
(2147483647
), тогда оно является действительным целым числом и, таким образом, может быть отменено до int
.
Это позволяет вам захватывать значения вне нормального диапазона 'int', а затем, когда вы возвращаете обратно в' int', значения вне '-2^32' и' 2^32-1' округляются вниз или вверх соответственно. –