Какой класс данных лучше использовать для хранения значения факториала в Java
Что проверяют
Знаете ли вы границы примитивов и поведение при переполнении, а не только слово BigInteger. Сильный ответ начинается с вопроса «до какого n нужно считать». Следом обычно просят оценить производительность или посчитать факториал очень большого числа.
Как отвечать
Разложите по диапазонам:
int: вмещает до 12! включительно, 13! уже не помещается;long: до 20! включительно, это 2 432 902 008 176 640 000 приLong.MAX_VALUEоколо 9,2·10¹⁸. 21! не влезает;double: доходит до 170!, дальшеInfinity, но точность в младших разрядах теряется гораздо раньше, для точных целых он не подходит;BigInteger: произвольная длина, ограничена только памятью. Это ответ, если n заранее не известно или больше 20.
Ключевая деталь: переполнение примитивов в Java молчаливое. 13! в int даёт 1 932 053 504, 21! в long вообще отрицательное число, исключения нет. Если остаётесь на long, используйте Math.multiplyExact: он бросит ArithmeticException при переполнении.
BigInteger неизменяемый: result.multiply(BigInteger.valueOf(i)) возвращает новый объект, его нужно присвоить. Начинают с BigInteger.ONE и считают циклом, а не рекурсией: рекурсия на десятках тысяч уровней упрётся в StackOverflowError.
Про скорость: на больших числах JDK сам переключается на алгоритмы Карацубы и Тоома-Кука. Если перемножать не подряд, а парами (дерево произведений), выходит заметно быстрее, потому что умножаются числа сопоставимой длины. Если нужна не точная величина, а порядок числа, хватит суммы Math.log(i).
BigDecimal здесь не нужен: факториал целый, масштаб и дробная часть только добавят накладных расходов.
Где спотыкаются
Говорят, что 20! уже не помещается в long. Помещается, это последний факториал, который влезает, и интервьюер часто проверяет именно эту границу.
Пишут result.multiply(...) без присваивания и получают на выходе единицу, потому что BigInteger не меняется на месте.
Выбирают double, «потому что он большой». Для факториала это неверный ответ: значение округлится, и сравнение с точным результатом не сойдётся.