Посвящается новичкам, которые недоумевают, почему значение в переменной в какой-то момент уходит в минус
Пример кода
public class Main {
static int IWantMore;
public static void main(String[] args) {
while (true) {
IWantMore++;
System.out.println(IWantMore);
if (IWantMore == 0) break;
}
}
}
С каждым новом заходом он прибавляет к IWantMore. Казалось бы, что цикл не остановиться, так как к моменту первой проверки if -ом значение будет 1, но это не так…
В консоли мы увидим следующие:
1
2
3
…
2147483646
2147483647
-2147483647
-2147483646
…
-3
-2
-1
0
Чем примечательно число 2147483647? Да это же максимальное значение int! Переведем это число в двоичный вид:
0 1111111111111111111111111111111 (1 + 31 знак — первый отвечает за знак перед числом: 0 — плюс, 1 -минус,, последующие за само число )
32 знака в оперативной памяти — именно столько выделяется под int
При прибавлении к 2147483647 единицы мы по идее должны получить следующие:
010000000000000000000000000000000 (33 знака)
Однако на int стоит жёсткое ограничение — 32 знака. Поэтому первый знак автоматически убирается и получается:
10000000000000000000000000000000 (32 знака)
Что эквивалентно -2147483647!
Как защититься?
Главный способ
Используйте long вместо int. В 99.9% случаях его хватает
Если long -а не хватает
java.Math.BigInteger
Если вы используете java, то вам повезло. Есть готовое решение — BigInteger. Я не буду расписывать что это такое, а просто дам линки на статьи.
Значение деления
Есть число 9999999999999999999999999. Поделим его на макс. значение int (на long тоже можно, но не нужно) и запишем этот результат в переменную double. Такое число легко восстановить.
Массив
Записывать число в массив из нескольких long -ов, сложив которые будет получаться это число //Не очень хороший способ, т.к. ест много оперативной памяти
Автор: danpetruk