Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737 Форумы портала PHP.SU :: Рекурсивная функция не хочет работать :)
Покинул форум
Сообщений всего: 11
Дата рег-ции: Авг. 2020
Помог: 0 раз(а)
Привет, помогите разобраться.
Проблема: всегда выводит кол-во попыток 1 и нужно много раз f5 жать, до результата, т.е. оно не "проваливается/рекурсит" саму себя до победы.
// Задача: функция 3 раза рандомит числа, от 0 до 5 и если конечная сумма меньше 14, то
// рекурсим и увеличиваем кол-во попыток на 1
function sum14($quantityTry)
{
for($i=0;$i<=3;$i++){// ШАГ 0. Запускаем цикл на 3 раза = 3 рандома
if($i==3){// ШАГ 2. После рандомов проверяем сумму
if($count<14){// Если сумма меньше 14
sum14($quantityTry++);// то рекурсимся и +1 к кол-ву попыток
}else{
return'Результат '.$count.'. За '.$quantityTry.' попыток';// итог
}
}
$count+=rand(0,6);// ШАГ 1. 3 раза рандомит и складывает сумму
}
}
$quantityTry=1;
echo sum14($quantityTry);// тут жестокая реальность противится моей воле :\
Спасибо
Мелкий
Отправлено: 26 Августа, 2020 - 11:03:14
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
А каким образом ваш рекурсивный вызов мог бы влиять на логику выполнения? Никаких побочных эффектов, а возвращаемое значение вы игнорируете. Что есть вызов функции, что нет его - воздух только греть.
----- PostgreSQL DBA
Vladimir Kheifets
Отправлено: 26 Августа, 2020 - 11:26:08
Частый посетитель
Покинул форум
Сообщений всего: 879
Дата рег-ции: Март 2017 Откуда: Германия, Бавария
Помог: 37 раз(а)
hehagog545 пишет:
Привет, помогите разобраться.
Проблема: всегда выводит кол-во попыток 1 и нужно много раз f5 жать, до результата, т.е. оно не "проваливается/рекурсит" саму себя до победы.
Добрый день!
Видимо, if($i == 3) в этом цикле не нужен.
sum14($quantityTry);// ф-ция отработала и записала итог работы в global $res;
echo$res;// вот его и выводим
Всем спасибо за участие
LIME
Отправлено: 26 Августа, 2020 - 16:26:24
Активный участник
Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010
Помог: 322 раз(а)
hehagog545 res надо передавать в вызов
глобальное состояние есть зло
функция должна быть чистой(это термин) - данные на вход и данные на выход и ничего более
никаких сайдэффектов
$res уже может существовать в системе и ты либо свою логику неверно выполнишь либо чужую сломаешь
static не сильно лучше
лучше сразу привыкай нормально делать
hehagog545
Отправлено: 26 Августа, 2020 - 18:22:35
Новичок
Покинул форум
Сообщений всего: 11
Дата рег-ции: Авг. 2020
Помог: 0 раз(а)
LIME спасибо. Про синоним зла и глобал слышал давно
Подправил, версия без глобал:
return$res='Результат '.$count.'. За '.$quantityTry.' попыток';
}
...
Подскажите почему оно не работает в данном применении? Спасибо
UPD:
(Предположение почему не работает с ретурном как следует: верно ли думать, что ретурн при рекурсии возвращает на 1 уровень вверх, а т.к. уровней углубления в рекурсию больше, от того и происходит ошибка. Т.к. ф-ция с ретурном работает, если:
1.повезло и она сгенерила с первого раза
2.также должно работать и для 2ух раз, а вот если глубина рекурсии больше 2ух, то уже ничего не выводит.)
(Добавление)
я так понимаю цель изучить рекурсию? потому что если можно логику сделать циклом то лучше избегать рекурсии - у нее лишние накладные расходы на сам вызов(выделение и освобождение памяти)
и нужно помнить о максимальной глубине вложенности - стэк не бесконечен (Добавление)
например числа фибоначи довольно быстро сдыхают на рекурсивном алгоритме
а циклом прям моментально считаются
hehagog545
Отправлено: 26 Августа, 2020 - 20:33:23
Новичок
Покинул форум
Сообщений всего: 11
Дата рег-ции: Авг. 2020
Помог: 0 раз(а)
LIME, подскажи по ретурну и рекурсии.
Ретурн он сразу в начало возвращает, выходя из всех уровней рекурсии или на 1 уровень вверх возвращает, как брэйк?
И можно ли задавать, как брэйку уровень выхода?
Спасибо.
PS Всё начиналось вроде с простой задачки, но в ходе решения стали возникать теоретические вопросы в которых оказался пробел - вот и копаюсь, с вашей помощью
LIME
Отправлено: 26 Августа, 2020 - 20:39:25
Активный участник
Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010
Помог: 322 раз(а)
ретурн возвращает в точку вызова где бы она не была
hehagog545 пишет:
как брэйк
боже упаси
как ты себе это представляешь? я значит такой говорю- "уважаемая ф-ция, посчитай мне пжлст вот это"
а мне в ответ- "пшел на фиг! я наверх куда-то отдам результат"
ф-ция не знает как она вызвана и что такое рекурсия вообще
ее вызвали -> она посчитала -> результат вернула вызвавшему коду
hehagog545
Отправлено: 26 Августа, 2020 - 21:01:27
Новичок
Покинул форум
Сообщений всего: 11
Дата рег-ции: Авг. 2020
Помог: 0 раз(а)
LIME спасибо, значит ретурн в рекурсивных ф-циях лучше не использовать, т.к. он просто не вернётся из недр, если глубина больше 1, то произойдёт логическая ошибка - как думаешь, за правило такую мысль можно выдать или есть исключения?
Покинул форум
Сообщений всего: 10732
Дата рег-ции: Нояб. 2010
Помог: 322 раз(а)
ты вообще не понял ничего
ретурн НУЖНО использовать
и только его
никаких глобал или статик
результат работы фции только в ретурне
hehagog545 пишет:
он просто не вернётся из недр
как это? вернется из самого первого вызова
накопившись во внетренних
глянь еще раз мои реализации рекурсии выше
попробуй мысленно выполнить действия (Добавление)
лучше я уже не объясню
удаляюсь (Добавление)
каждый вызов это новый экземпляр фции
hehagog545
Отправлено: 27 Августа, 2020 - 09:29:44
Новичок
Покинул форум
Сообщений всего: 11
Дата рег-ции: Авг. 2020
Помог: 0 раз(а)
LIME ок, спасибо, я не правильно представил себе работу ретурна
Объясните пожалуйста почему в этом примере счетчик работает: Листинг 1
return$res='Результат '.$count.'. За '.$quantityTry.' попыток';
}
}
echo sum14();
И ещё одно недоразумение увиделось. В листинге 1'Результат' бывает равени 16 и 17 и 18.
Как такое может быть, если максимальное рандомное число 5 и оно суммируется не более 3ёх раз?
(5 * 3 = 15 // максимум)
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.