Java

Вычислить факториал числа с помощью рекурсии

Вот такой код придумал:

static double f = 1;
static long i = 1;

public static double factorial(long in) {
if(i > in) {
return f;
}
f *= i;
i++;
factorial(in);

return f;
}

Всё правильно?
Ермек Мамаев
Ермек Мамаев
21 258
Слишком переусложнённо и с ненужными внешними переменными. Всё проще:

public static double fact(long n) { return n <= 1? 1.0 : fact(n - 1) * (double)n; }
РР
Руслан Руслан
71 522
Лучший ответ
Ермек Мамаев Как ваш код работает не понял.
Мой проще понять, хотя и слишком много буков лишних.
Ермек Мамаев А эта рекурсия часто требуется в реальном программировании?
Дмитрий Головин а за каким double?
Дмитрий Головин и ваш метод будет считать факториал даже для отрицательного числа...?
Неправильно. Тут, фактически, никакой рекурсии нет, поскольку не меняется аргумент рекуррентной функции. За глобальные переменные в мои времена тоже расстреливали в детстве из рогатки. Что будет, если я захочу посчитать произведение факториалов? Посчитай factorial(4)*factorial(3), например. Правильный ответ 144, а у тебя будет 24.
Ермек Мамаев 24 у нас получилось из-за использования глобальной переменной?
Ермек Мамаев А эта рекурсия часто требуется в реальном программировании?
Ермек Мамаев Реально же рекурсия нужна в основном для обхода всяких деревьев типа файловой системы и в алгоритмах сортировки?
Простому кодеру вряд ли потребуется писать с нуля такие алгоритмы сортировки, максимум потребуется обойти деревья типа каталогов и файлов в файловой системе или построить вложенное меню?
у вас есть вызов метода из этого метода... т. е. какая-то рекурсия у вас есть...
всё остальное.... неверно...
Алексей Иванов
Алексей Иванов
92 379
Ермек Мамаев Та я уже понял.
А эта рекурсия часто применяется? Она нужна в основном, чтобы всякие деревья обходить?
Вообще, лучше использовать long в качестве возвращаемого значения. Это более понятно, нежели когда возвращается double. Даже несмотря на то, что Double.MAX_VALUE > Long.MAX_VALUE. Если нужно считать прямо супер огромные значения факториалов, то во-первых, использовать рекурсию точно менее продуктивно, нежели циклы, во-вторых, для очень больших чисел лучше тогда использовать тип BigInteger, ибо и double не резиновый, а BigInteger условно безразмерный.
По определению, если его не строго определять, то n! = (n - 1)!*n. Из такого определения видно, что ожидается, что изнутри функции факториала, будет вызываться та же функция на аргументе, который меньше на 1. И так до тех пор, пока не дойдем до 1. Получается:
long fact(long n) {
if (n == 1) {
return 1;
}

return n * fact(n - 1);
}

Можно заинлайнить, чтобы просто одна строчка была.

Вот реализация на BigInteger:
BigInteger fact(BigInteger n) {
if (n.equals(BigInteger.ONE)) {
return BigInteger.ONE;
}

return n.multiply(fact(n.add(BigInteger.ONE.negate())));
}
Алекс G
Алекс G
13 926
Алекс G Кстати. В моей реализации нет гварда на отрицательные числа и на 0 в качестве входного значения. Факториал нуля - это 1. Поэтому лучше тогда поставить гвард
if (n == 0) вместо if (n == 1). Гвард на отрицательные числа можно поставить до вызова данной функции, чтобы эта функция занималась поиском факториала уже на корректных данных.