Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Не могу понять тему "Рекурсии" и итерационный цикл "for"
 
 автор: Wita1y   (06.05.2006 в 14:26)   письмо автору
 
 

Честно признаюсь. Искал и не нашел ничего по этой теме в поиске. Извините меня, может плохо искал. И напишу то что я действительно часто не могу подружится с вашим поисковиком.

Вот данная задача по этой теме:

1-ый скрипт:
<?php
function degree($x$y)
{
if(
$y)
{
return 
$x degree($x$y-1);
}
return 
1;
}
echo(
degree(24));
?>

Результат 16.
1. Вот как получилось 16 ?
2. На каком этапе происходит тормозиловка скрипта?
3. Что он вычисляет там?
Если можно объясните поподробнее об этом скрипте. (Пожалуйста пошагово).

2-ой скрипт (Итерационный вариант этого вычисления):
<?php
function degree($x$y)
{
for(
$result 1$y 0; --$y)
{
$result *= $x;
}
return 
$result;
}
echo (
degree(2,4));
?>

Здесь намного легче код понять, но все равно не въезжаю. :-(
Только вижу что этот скрипт быстрее выполняется.

Вот for цикл:
for($i=0; $i <= 5; $i++) // Выводит от 0 до 5. Понятьно все.

for($result = 1; $y > 0; --$y) // А вот это, блин ... Ступор.

Заранее спасибо.

   
 
 автор: cheops   (06.05.2006 в 14:40)   письмо автору
 
   для: Wita1y   (06.05.2006 в 14:26)
 

Лучше переписать более понятно
<?php 
  
function degree($x$y
  { 
    if(
$y) return $x degree($x$y-1); 
    return 
1
  } 
  echo(
degree(24)); 
?>

1. Вот как получилось 16 ?
2. На каком этапе происходит тормозиловка скрипта?
3. Что он вычисляет там?
<?php
  
// 0 - это false, всё что олично от нуля - true
  
if(4) return 2*degree(23);
  
// degree(2, 3)
  
if(3) return 2*degree(22);
  
// degree(2, 2)
  
if(2) return 2*degree(21);
  
// degree(2, 1)
  
if(1) return 2*degree(20);
  
// degree(2, 0)
  
if(0) return 2*degree(2, -1);  // А вот это уже не срабатывает 0 - это false
  
return 1;
  
// Переходим в  degree(2, 1) и degree(2, 0) = 1
  
if(1) return 2*1;
  
// Переходим в  degree(2, 2) и degree(2, 1) = 2
  
if(2) return 2*2;
  
// Переходим в  degree(2, 3) и degree(2, 2) = 4
  
if(3) return 2*4;
  
// Переходим в  degree(2, 4) и degree(2, 3) = 8
  
if(4) return 2*8// 16
?>

   
 
 автор: Wita1y   (06.05.2006 в 18:29)   письмо автору
 
   для: cheops   (06.05.2006 в 14:40)
 

Почти исчерпающий ответ но все же остались вопросы по этому скрипту:
<?php 
  
function degree($x$y
  { 
    if(
$y) return $x degree($x$y-1); 
    return 
1
  } 
  echo(
degree(24)); 
?>


> // 0 - это false, всё что отлично от нуля - true
1. Где написано, что функция по умолчанию имеет значение false а не true?

> if(0) return 2*degree(2, -1); // А вот это уже не
>срабатывает 0 - это false
2. Здесь мне предполагается то что это исчезает из цикла так как он не оправдал true.

> return 1;
3. Почему return возвращает цифру а не переменную?
Каким боком он влияет на вывод результата?
И если я поменяю на -1(то будет -16) или 2 (то будет 32).
Он лишь должен выполнять возвращение значения или я что-то путаю. :-(
Мне думается когда до дошел 0 цикл то он возвращается обратно с назначенной ему 1 и только после этого идет решения уже к готовому результату.
И само это число на что в итоге влияет?

4. То что он доходит до 4 и выдает результат, это понятно.
Мне не понятен смысл самого решения уже после.
<?php
// Переходим в  degree(2, 1) и degree(2, 0) = 1
if(1) return 2*1;
// Переходим в  degree(2, 2) и degree(2, 1) = 2
if(2) return 2*2;
// Переходим в  degree(2, 3) и degree(2, 2) = 4
if(3) return 2*4;
// Переходим в  degree(2, 4) и degree(2, 3) = 8
if(4) return 2*8// 16
<?


Извиняйте меня еще раз если вам приходится мне разжевывать досконально.

   
 
 автор: Trianon   (06.05.2006 в 19:37)   письмо автору
 
   для: Wita1y   (06.05.2006 в 18:29)
 


<?php 
  
function degree($x$y
  { 
    if(
$y) return $x degree($x$y-1); 
    return 
1
  } 
  echo(
degree(24)); 
?> 


Этот код имеет смысл слегка видоизменить, и читать так:


<?php
  
function degree($x$y// функция  degree предназначена для
  
{           // вычисления $x в степени $y
              // причем степень предполагается целая неотрицательная

    
if($y == 0)  // при возведении в нулевую степень мы получаем
          
return 1;  // в результате единицу независимо от того, что возводим

                    // более высокую степень можно вычислить,
                    // если  домножить на $x степень с
                    // показателем на единицу меньше,
                    // (напр. куб х = х * квадрат х)
    
return degree($x$y-1) * $x// при условии, если мы знаем,как её вычислить.
  
}

  echo(
degree(24));  // а это попытка вычислить 2 в степени 4
                       //  и вывести результат c помощью echo
?>


рекурсивный вариант тратит больше времени хотя бы потому, что на каждый вызов функции нужно создать набор локальных переменных, а по завершении вызова этот набор уничтожить. Правда я сильно сомневаюсь, что на вызове degree(2,4) Вы смогли заметить разницу в быстродействии.

   
 
 автор: cheops   (06.05.2006 в 21:34)   письмо автору
 
   для: Wita1y   (06.05.2006 в 18:29)
 

1) Это старое правило - родилось оно в C - там нет булевого типа и ключевых слов true и false, поэтому false - это 0, а true - это всё отличное от нуля. Так как добрая половина языков программирования это C-подобные языки, то они придерживаются этого же правила, хотя в них давно уже ввели булевый тип вместе с true и false.

2) Не понял, требуются ли какие-либо комментарии и если требуются, то какие?

3) Этим я хотел показать, что переменная принимает значение 1
>Мне думается когда до дошел 0 цикл то он возвращается обратно с назначенной ему 1 и только
>после этого идет решения уже к готовому результату.
Да, вы всё правильно поняли.

4) Не очень понятно, что вызывает затрудение, если назначение функции, то без контекста она у любого вызовет недоумнее, так как итеративным путём можно получить результат быстрее - мне кажется это просто демонстрация рекурсии.

   
 
 автор: cheops   (06.05.2006 в 14:46)   письмо автору
 
   для: Wita1y   (06.05.2006 в 14:26)
 

for($result = 1; $y > 0; --$y) // А вот это, блин ... Ступор.

Цикл for - очень гибкий, в нём может быть несколько переменных, не быть тела цикла - правда плата за это низкая читабельность.
Приведённый выше цикл говорит о следующем - нужно на каждом этапе цикла переменной $result присваивать 1, и выполнять цикл до тех пор, пока $y > 0, при этом на каждом этапе отнимать от $y единицу.
Циклы for могут быть достаточно изощрёнными, например,
<?php 
  
for($i 0$j 10$i != $j$i++, $j--, print("$i - $j<br>"));
?>

выведет
1 - 9
2 - 8
3 - 7
4 - 6
5 - 5

только лучше не употреблять их без надобности - это дурной тон.

   
 
 автор: Trianon   (06.05.2006 в 16:02)   письмо автору
 
   для: cheops   (06.05.2006 в 14:46)
 

где можно почитать про операцию "запятая" ?
заголовок for( ... ; ... ; ... ) - единственный контекст, в котором её можно применять?

P.S. comma - my lovely C-operator ....

   
 
 автор: Саня   (06.05.2006 в 17:09)   письмо автору
 
   для: Trianon   (06.05.2006 в 16:02)
 

Можно использовать запятые:
<?php
$k 
10;
for ( 
$i 1$s 0$i <= $k$s += ++$i $i );
print 
$s;

for ( 
$i 1$s 1$k 15$i $k$i++, $s *= ) {
  print 
'$i='.$i.'; $s='.$s.';<br/>';
}
?>

   
 
 автор: Trianon   (06.05.2006 в 17:21)   письмо автору
 
   для: Саня   (06.05.2006 в 17:09)
 

Я больше скажу - во втором выражении for (в условии повтора) их тоже можно использовать.

for      (
   $r = 0,
   $query = "SELECT * FROM tab",
   $res = mysql_query($query),
   $rowno = mysql_num_rows($res)
          ;
   $rows = mysql_fetch_array($res),
   $rows != null
          ;
    $r++
          ) 
     {
          echo "$r .";
          print_r($rows);
     }

Меня же интересует, где описаны правила, определяющие, когда можно применять эту операцию, а когда нельзя. Потому что по всему выходит, что нельзя её упреблять практически нигде.

   
 
 автор: Саня   (06.05.2006 в 17:29)   письмо автору
 
   для: Trianon   (06.05.2006 в 17:21)
 

Меня же интересует, где описаны правила...
В документации ничего такого не сказано. Я узнал о возможности использовать запятую в циклах из книги о Си++. Думаю правила использования этого оператора идентичны правилам в си.

   
 
 автор: Trianon   (06.05.2006 в 18:08)   письмо автору
 
   для: Саня   (06.05.2006 в 17:29)
 

Есть одно упоминание. В разделе с таблицей приоритетов и направлениями ассоциативности операций. Других я не видел.

До поста cheops'a я думал, что её вообще забыли реализовать, а таблица осталась слизанной с оригиналов пера K&R. Но сейчас вообще ничего не понимаю. Нельзя же реализовать операцию в for и случайно забыть о ней во всех остальных местах?

   
 
 автор: cheops   (06.05.2006 в 21:28)   письмо автору
 
   для: Trianon   (06.05.2006 в 18:08)
 

Все описания в справочниках по C и Perl - PHP описан очень безобразно - хуже мануала, я больше нигде не видел. Да нормально вообще говоря запятая действует, помимо for, только в таком контексте (могу врать - может ещё где срабатывает)
<?php
  
echo "Hello ""world!";
?>

   
 
 автор: Trianon   (06.05.2006 в 21:47)   письмо автору
 
   для: cheops   (06.05.2006 в 21:28)
 

В этом контексте она тоже не действует. Точнее действует семантически ненормально.
Запятая, как операция, а не как разделитель параметров, должна вычислить и тут же выкинуть значение своего левого операнда, а затем заняться правым.
echo 1,2 с позиций С-подобного языка, должно напечатать двойку.
Ничего подобного не происходит. Печатается 12. Возникает впечатление, что языковая конструкция echo воспринимает любое количество аргументов и выводит последовательно один за другим.
Но не тут-то было. Стоит взять этот список аргументов в скобки, написав echo(1,2); и тут же оказывается, что тогда echo считает, что у нее один аргумент. С ошибочным синтаксисом: parse error, unexpected ',' .

   
 
 автор: cheops   (07.05.2006 в 12:11)   письмо автору
 
   для: Trianon   (06.05.2006 в 21:47)
 

Согласен... с позиции целостности языка лучше бы разработчики PHP вообще больше кроме как в for запятую не использовали - так как ни к чему кроме как запутанному коду она не приведёт.

   
 
 автор: Wita1y   (08.05.2006 в 11:15)   письмо автору
 
   для: cheops   (06.05.2006 в 21:28)
 

>Все описания в справочниках по C и Perl - PHP описан очень
>безобразно - хуже мануала, я больше нигде не видел. Да
>нормально вообще говоря запятая действует, помимо for,
>только в таком контексте (могу врать - может ещё где
>срабатывает)

И все-таки.
1. Что будет правильнее: запятая(без скобок) или точка(со скобками)?
2. И как это может повлиять в дальнейшем?
<?php
echo  "Hello ""world!"// так?
echo  "<br>";
echo (
"Hello ""world!"); // или так?
?>

   
 
 автор: cheops   (08.05.2006 в 18:17)   письмо автору
 
   для: Wita1y   (08.05.2006 в 11:15)
 

Лучше использовать точку - увидеть её ожидают 90% программистов, даже те кто знаком с запятой - будут ворчать.

   
 
 автор: Wita1y   (07.05.2006 в 13:25)   письмо автору
 
   для: cheops   (06.05.2006 в 14:46)
 

<?php 
function degree($x$y

for(
$result 1$y 0; --$y

$result *= $x

return 
$result

echo (
degree(2,4)); 
?>


Если я правильно понял, то вычисление происходит таким образом:
<?php
for ($result 103)
1*2// $result = 2

for ($result 102)
1*2// снова $result = 2

for ($result 101)
1*2// опять $result = 2

for ($result 100)
1*2// тоже самое $result = 2

for ($result 10; -1// !true
1*2// и оно же $result = 2
return 2;
// Далее пошло вычисление результата.
return 2*1// = 2 
return 2*2// = 4 
return 2*4// = 8 
return 2*8// = 16
echo
?>

Прокоментируйте пожалуйста и укажите на мои ошибки, если конечно же имеются.

Всем спасибо.

   
 
 автор: woodfairy   (08.05.2006 в 13:11)   письмо автору
 
   для: Wita1y   (07.05.2006 в 13:25)
 

то, что переменной $result присваивается 1 на каждом шаге итерации - полный бред
в цикле for(a;b;c)
a выполняется один раз на этапе инициализации цикла,
b - условие, которое проверяется каждый раз при входе на следующую итерацию, и если оно не выполняется, то цикл завершается,
c выполняется на каждой итерации в самом конце

а вообще никого не слушай - проверь сам:

<?php 
function degree($x$y

for(
$result 1$y 0; --$y

echo 
"x = $x; y = $y; result = $result<br>";
$result *= $x

return 
$result

echo (
degree(2,4)); 
?> 


это тебе даст информацию по каждому шагу цикла
удачи,
Надя

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования