Рекурсия - это петлевая конструкция, которая исходит из функциональных языков. Так что да, как отмечали другие, ваша функция работает некорректно, потому что ветвь true вашего оператора if
ничего не возвращает. Тем не менее, у меня есть дополнительные замечания по поводу кода
function fact($n, $p = 1) {
if ($n > 1) {
// this makes it hard to reason about your code
$p *= $n--;
return fact($n, $p);
} else {
return $p;
}
}
Вы на самом деле мутирует две переменные здесь в один выражение. Это умно, если вы пытаетесь сохранить код более коротким, но на самом деле есть еще лучший способ.
function fact($n, $p = 1) {
if ($n > 1) {
$p *= $n--;
// just compute the next values; no need to update $p or $n
return fact($n - 1, $p * $n);
} else {
return $p;
}
}
Теперь мы не должны думать о том, как $p
и $n
изменения в индивидуальном порядке. Мы просто знаем, что мы снова вызываем fact
с следующими значениями для каждого состояния $p
и $n
.
Имейте в виду, что эти принципы настолько сильны в некоторых функциональных языках программирования, что переназначение переменных нравится $p
и $n
даже не разрешено.
Наконец, мы должны говорить о вашем вашей утечке API, $p
. Если кто-то указать значение при вызове fact
, они могли бы получить неправильный ответ или вызвать ошибку
// bad !
fact(5, 10); // => 1200
Это возможно только потому, что $p
фактически подвергается в общественном API.Чтобы обойти эту проблему, у вас есть несколько вариантов
Один из них сделать, как @RonaldSwets предлагает:
function fact($n) {
// 1 is the base case, like you had for $p in your code
if ($n == 0)
return 1;
// otherwise return $n times the next value
else
return $n * fact($n - 1);
}
Другой использовать вспомогательную функцию, которая предназначена только для личного пользования
// function used by `fact`
function fact_aux ($n, $p) {
if ($n == 0)
return $p;
else
return fact_aux($n - 1, $p * $n);
}
// function meant to be used by others
function fact ($n) {
return fact_aux($n, 1);
}
попробуйте 'return fact ($ n, $ p);' –
Поскольку вы возвращаетесь только в базовый регистр, результаты не базового случая никогда не передаются обратно. Как сказал выше, вам нужно вернуться. – Carcigenicate