Как работать с очень большими целыми числами
Короткий ответ
int хранит числа примерно до 2 миллиардов, long — до 9,2 квинтиллиона. Всё, что больше, хранит BigInteger:
void main() {
IO.println(Integer.MAX_VALUE);
IO.println(Long.MAX_VALUE);
var big = new BigInteger("123456789012345678901234567890");
IO.println(big.multiply(big));
}Результат:
2147483647
9223372036854775807
15241578753238836750495351562536198787501905199875019052100Арифметика
У BigInteger нет операторов — вместо +, -, *, / вызываются методы:
void main() {
var a = BigInteger.valueOf(2).pow(100);
var b = BigInteger.TEN;
IO.println(a);
IO.println(a.add(b));
IO.println(a.mod(BigInteger.valueOf(7)));
}Результат:
1267650600228229401496703205376
1267650600228229401496703205386
2Сравнение
Сравнивайте через compareTo() или equals(), а не через < и ==:
void main() {
var a = new BigInteger("1000000000000000000000");
var b = a.add(BigInteger.ONE);
IO.println(a.compareTo(b) < 0);
IO.println(a.max(b));
}Результат:
true
1000000000000000000001Обратно в long
longValueExact() вернёт long, если значение помещается, иначе выбросит исключение — так ошибка не пройдёт незамеченной:
void main() {
IO.println(BigInteger.valueOf(42).longValueExact());
IO.println(BigInteger.TWO.pow(70).longValueExact());
}Результат:
42
Exception in thread "main" java.lang.ArithmeticException: BigInteger out of long rangeЧастая ошибка
Записать большое число литералом. Целый литерал без суффикса — это int, и компилятор отказывается:
void main() {
long big = 3000000000;
IO.println(big);
}Результат:
Main.java:2: error: integer number too largeДля long добавьте суффикс L: 3000000000L. Для ещё больших чисел — new BigInteger("…").
Функции из этого ответа
- BigInteger — Целое число любого размера — когда не хватает даже long.
- Integer.MAX_VALUE — Наибольшее значение типа int; рядом — Integer.MIN_VALUE.