Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

Функция - как?

...::: Приветствую, comp :::...

function TForm1.MulNumber(index: Integer): Integer;
begin

if Index=1 then
begin
Result:=1;
exit;

end;
Result:=Index*MulNumber(index-1);

end;

Вот если эту функцию вызвать ( MulNumber(5) ) то она возвратит
факториал числа 5 - 120, но почему ведь перед выходом ( exit; ) стоит
присвоение ( Result:=1; ) и ведь это значит что функция должна
возвратить число 1, но почему получается иначе?

= = = = = = = = = = = = = = = = = = = =
...::: by GENEMI :::...

Номер выпуска : 4281
Возраст листа : 566 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/348069
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sat, 9 Apr 2005 20:26:47 +0300 (#348069)

 

Ответы:

Здравствуйте, GENEMI.



Потому, что это последнее умножение на единицу. Функция в любом случае
должна что-то вернуть. И получается, что когда она входит сама в себя,
она накапливает числа, которые потом, после выхода перемножаются.
Единица - последнее.

Ответить   Andrey Yakushev Sat, 9 Apr 2005 22:44:35 +0400 (#348093)

 

...::: Приветствую, Andrey Yakushev :::...



Я все равно не понял :( объясните поподробнее plz.

= = = = = = = = = = = = = = = = = = = =
...::: by GENEMI :::...

Номер выпуска : 4296
Возраст листа : 568 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/348526
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sun, 10 Apr 2005 23:26:40 +0300 (#348526)

 

Здравствуйте, GENEMI.

Вы писали 11 апреля 2005 г., 0:26:40:



Уже не получится. Чтобы понять, сделайте следующее:
На листочке нарисуйте таблицу. В столбцах будут переменные, а в
строчках - операторы паскаля. Возьмите небольшое стартовое число
(3-4) и заполняйте ячейки таблицы, в первом столбце записывая
оператор, который выполнился. Только учтите, что заходя внутрь
рекурсии создаётся новый набор внутренних переменных. Таким образом, у
Вас будут index', index'', index''' и т.д.
Проведёте всю эту отладку, сразу всё станет понятно.
Я, когда-то на заре программирования писал на ассемблере свою функцию
деления. Она никак не шла. Тогда я мелом на доске вписывал битовые
значения регистров в ячейки. Таким образом, нашёл ошибку.

Ответить   Andrey Yakushev Mon, 11 Apr 2005 08:28:09 +0400 (#348574)

 

Нужны алгоритмы быстрого теста касания объектов в виртуальной среде.
Причем, среды имеют разную размерность и не пересекаются. В одном случае
нужен быстрый плоский тест, в другом -- объемный. Примеры применения --
тесты попадания мячиком в ящик в арканоиде и пулей в монстра в
стрелялке.

С уважением Атавин Т. А.
atavin_***@p*****.ru

Номер выпуска : 4341
Возраст листа : 569 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/349713
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 12 Apr 2005 13:44:48 +0700 (#349713)

 

Нужны быстрые алгоритмы индексации каркасной сети для подготовки
описателя объекта для его визуализации в реалтайме при одновременном
редактировании самого объекта в редакторе трехмерных моделей или при
одновременном его движении (и деформации) в игре. В первом случае
входные параметры: ссылка на старый описатель, код добавляемого
примитива (стандартной фигуры или стандартного тела) и ссылка на список
параметров этого примитива (то есть размеров и координат). Во втором:
ссылка на старый описатель, код деформации, ссылка на ее описатель
(список узлов, координаты которых известны точно и их новых координат).
В первом случае желательно иметь максимальное число поддерживаемых
примитивов. Во втором при движении обязательно должен поддерживаться
перерасчет координат тех узлов, для которых координаты не заданы, а при
деформации такой перерасчет желателен (если расчет правдоподобной
деформации не удастся реализовать быстро, то скорее всего придется
отказаться от детализации деформируемых объектов, например, кожи кистей
рук).
С уважением Атавин Т. А.
atavin_***@p*****.ru

Номер выпуска : 4344
Возраст листа : 569 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/349716
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 12 Apr 2005 13:44:48 +0700 (#349716)

 

<skipнуто>

Это что, с самого начала такие примеры? Всё больше и больше
проникаюсь"симпатией" к твоему учебнику 8-(.
Есть такое тождество: N! = N*(N-1)!. Причём N предполагается целым
положительным. Это тебе понятно, раз ответил, что функция работает правильно

при передаче ей значения 5 в качестве аргумента. Поэтому можно сказать, что
определение факториала рекурсивно: факториал >любого< числа есть
произведение этого самого числа на факториал предыдущего. "Факториал
предыдущего", понятное дело, можно вычислять аналогично.
Этот факт и демонстрирует приведённая тобой функция. Она отсылает
"предыдущее" к себе самой для вычисления (N-1)! и умножает результат на N.
Его и возвращает. Но!
Если постоянно отсылаться к себе самой, то функция никогда не закончится.
Дойдёт до нуля, перейдёт в область отрицательных чисел и т.д. Это только в
теоретических рассуждениях можно оперировать бесконечными рядами. Математики

(а также и другие умники, использующие математический аппарат) часто этим
пользуются, но на практике это неприемлимо. Надо где-то остановиться, иначе
функция просто зависнет (реально ты вместо зависания получишь переполнение
стека, но это в данным момент не принципиально - суть не в характере
проявления ошибки, а наличии самой ошибки). Поэтому слово >любой< я выделил.

В этой функции остановка предусмотрена при N=1. Когда функции передаётся
единица, она НЕ вызывает себя снова, а сразу возвращает результат, который,
как известно 1!=1.
Обрати внимание, что функция не может вернуть результат N!, пока не известен

результат (N-1)!. Поэтому все вызванные функции, ждут друг друга в порядке
вызова, пока их более поздние вызванные иркарнации не закончат свою работу.
Первой закончит та, которая вызвана самой последней. Ей как раз и будет
передана единица. Закончив работу, она даёт возможность своей предыдущей
"работнице" выполнить-таки умножение и тоже вернуть свой результат "ещё
более предыдущей". И т.д. До самого начала.
Ну, а Exit там стоит как раз для того, чтобы "досрочно" завершить работу
функции, не выполняя остальных операторов. Ведь Result:=1 не самый последний

оператор в функции, и если бы Exit не было, то так и продолжились бы они
исполняться, что в этом случае лишнее. Обрати внимание, что Exit находится
внутри условного оператора, и следовательно НЕ исполняется, если Index не
равен 1.
Впрочем, можно было бы обойтись и без Exit. Чтоб было понятнее, вот:

if Index=1
then Result := 1
else Result := Index * MulNumber(index-1);

Этот код функционально аналогичен приведённому тобой.
Теперь Ok?

--
С уважением, boroden***@s*****.ru

Номер выпуска : 4299
Возраст листа : 568 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/348608
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Mon, 11 Apr 2005 09:14:36 +0400 (#348608)

 

...::: Приветствую, Шматко А.А. :::...

<cut>

Все равно ни как не уловлю смысл :(

Хотя я подозреваю что когда функция вызывает саму себя -
MulNumer(Index-1) то результат который хранится в result переходит
как-то в нее снова.

Но так вроде бы все понятно, но я все равно не пойму как 1-ца влияет
на результат, ведь после нее следует exit и функция завершает свою
работу и ни каких больше умножений на 1-цу дальше нет.

Но мне кажется что у функции есть какие-то как бы скрытые переменные в
которые она записывает результат предыдущего результата.
Ведь как я знаю при выходе из функции она опустошает все свои
локальные переменные, "но тут мне в создание приходит одно понятие":
Ведь когда функция ВЫЗЫВАЕТ САМУ СЕБЯ она не завершает свою работу и
следовательно не опустошает свои локальные переменные (это я про
result ведь как я знаю она идентична названию функции), но мне эта
часть понятна .

Некоторые говорят что единица участвует в умножение, я понял бы это если б
код был такой:
if Index = 1 then
RESULT := 1*Index;
exit;
end;
...

тогда вроде бы понятно, но ведь как происходит последнее умножение на 1-цу если
там нет ни каких операторов? :(

Или при присвоение значения в RESULT он уже автоматически помнит
команду INDEX*MulNumber , т.е. умножение INDEX
на саму функцию.
Такое чувство что функция имеет какие-то скрытое значение, то какое я
наверное и не пойму :(

= = = = = = = = = = = = = = = = = = = =
...::: by GENEMI :::...

Номер выпуска : 4305
Возраст листа : 568 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/348888
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Mon, 11 Apr 2005 16:25:10 +0300 (#348888)

 

Было в листе такое сообщение: "Есть такое тождество: N! = N*(N-1)!.
Причём N предполагается целым
положительным. Это тебе понятно, раз ответил, что функция работает
правильно

при передаче ей значения 5 в качестве аргумента. Поэтому можно сказать,
что
определение факториала рекурсивно: факториал >любого< числа есть
произведение этого самого числа на факториал предыдущего. "Факториал
предыдущего", понятное дело, можно вычислять аналогично.
Этот факт и демонстрирует приведённая тобой функция. Она отсылает
"предыдущее" к себе самой для вычисления (N-1)! и умножает результат на
N.
Его и возвращает."

Вопрос: а зачем так делать? Не можете избавиться от рекрусии -- не
пишите таких функций, займитесь теми, которые определены циклически --
лучше получатся. Реально на машине всегда любая рекурсия транслируется в
двойной цикл: сначала функция вызывает себя много раз с разными
аргументами, что эквивалентно обратному циклу (for i:=n downto 1 do
f:=i;)? А потом подставляет полученные значения в определение функции в
прямом порядке, что
Тоже эквивалентно циклу, но уже прямому (for i:=1 to n do; r:=r*f;).
Функция будет работать быстрее, если ее сразу запускать с прямого цикла,
а для этого надо ее определять циклически.
Кстати, переполнение может быть и другим. В данном случае переполняется
стек, а само значение обращается в нуль, но в других случаях возможно
переполнение отдельных ячеек по разрядности.
А если все таки хочется писать функции, объявленные рекурсивно -
займитесь сначала их анализом, постарайтесь выявить в них цикличность
процесса вычислений. Изучите теоретически как можно больше таких
функций, а потом уж пишите код.
А для того, чтобы было понятнее, почему так важно избавляться от
рекурсии приведу такой пример: рекурсивная процедура вычисления
определителя матрицы справилась только с матрицей пятого порядка, а на
шестом получила переполнение (кстати, как раз стека), циклическая же
справляется с матрицами, порядок которых измеряется десятками тысяч. А
теперь представьте себе такой вариант: функция возрастает по модулю
(имеется в виду не наш модуль -- mod, а математический -- abs) с ростом
аргумента, но очень медленно. Тогда следует ожидать, что машина сможет
вычислять ее для больших аргументов. На самом же деле при большом
аргументе переполнение стека может происходить быстрее, чем отдельных
ячеек, например, результата. Особенно это проявляется для убывающих по
модулю и циклических функций, которые не могут переполнять результат, но
при рекурсивном определении сохраняют способность переполнять стек.
Попробуйте, например, рекурсивно сдвигать аргумент синуса при больших
его значениях на один период в сторону нуля, пока модуль аргумента не
станет меньше полупериода. А потом посмотрите, что из этого получится
при значениях аргумента, которые потребуется сдвигать хотя бы на
миллиард периодов -- 2000000000*pi (при частоте 1700 МГц и выше
циклический сдвиг произойдет меньше, чем за одну секунду, а переполнение
счетчика цикла вообще не возможно, если обойтись без счетчика).

Кстати, я и сам не грешу избыточным применением рекурсии. Один раз
вообще додумался объединить в одном модуле Крамера (причем, как раз
рекурсивного) с Гауссом (конечно, циклическим) и предлагать потом этот
модуль другим программистам в качестве модуля матподдержки для всех их
программ, решающих системы уравнений.

С уважением Атавин Т. А.
atavin_***@p*****.ru

Номер выпуска : 4342
Возраст листа : 569 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/349714
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 12 Apr 2005 13:44:48 +0700 (#349714)

 

<skipнуто>

М-м-м... Ты б трэд отмотал назад, что ли, перед тем как читать лекцию о
рекурсивности и итеративности.
Чтоб избавить от хлопот, поясню, с чего началось: человек увидел в учебнике
пример функции, не разобрался, как оно это всё работает и попросил
разъяснений. Вот в общем-то и всё.
О недостатках рекурсивных алгоритмов большинству присутствующих здесь, я
думаю, известно. А вот из твоего пространного сообщения не понятно, имеешь
ли ты понятия об их преимуществах. Разверни-ка в итерацию функцию Аккермана,
плз. Не ради бахвальства, а для сравнения: мне понадобилось два дня, из
которых один ушёл на теоретические математические исследования предмета.
Инета у меня не было. Впрочем и сейчас нет, только почта. А рекурсивный
вариант пишется в пол-минуты, хоть и работает ~вдвое медленнее, и стек
пожирает в немыслимых размерах.
Так что истина, как всегда, не по краям, а между.

Номер выпуска : 4356
Возраст листа : 570 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/350092
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   "Шматко А.А." Wed, 13 Apr 2005 14:28:22 +0400 (#350092)

 

Здравствуйте, GENEMI,

Saturday, April 9, 2005, 11:26:47 PM, вы писали:

Обычный пример использования рекурсии. Функция запускается с
параметром = 5. И расчитывает себя до тех пор, пока не дойдет до
единицы. И выводится результат не последнего значения, а факториала
5-ти.

Ответить   Mon, 11 Apr 2005 08:52:45 +0600 (#348561)

 

...::: Приветствую, Шистеров Павел :::...

Но ведь в конце Результату присваивается 1

= = = = = = = = = = = = = = = = = = = =
...::: by GENEMI :::...

Номер выпуска : 4302
Возраст листа : 568 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/348729
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Mon, 11 Apr 2005 11:30:20 +0300 (#348729)

 

Здравствуйте, GENEMI,

Monday, April 11, 2005, 2:30:20 PM, вы писали:

Тут уже лучше меня сущность рекурсии объяснили. Результат равный 1
присваивается не главному вызову функции, а последнему.
Ну-у, типа пример:
Результат = Фак(5) =120
фак(5)= 5*фак(4) =120
фак(4) = 4*фак(3) =24
фак(3) = 3*фак(2) =6
фак(2) = 2*фак(1)=2
фак(1)=1(exit)

Ответить   Mon, 11 Apr 2005 16:14:17 +0600 (#348775)

 

Подскажите, пожалуйста, как в Borland Delphi 8 Architect Edition
создавать MDI приложения. В частности, меня интересует код, создающий на
этапе исполнения приложения новую форму документа, код, закрывающий
форму документа и свойство, разрешающее такое закрытие.

С уважением Атавин Т. А.
atavin_***@p*****.ru

Номер выпуска : 4343
Возраст листа : 569 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/349715
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Tue, 12 Apr 2005 13:44:45 +0700 (#349715)

 

Привет GENEMI,

Вы мне письмо написали 9 апреля 2005 г. (суббота), а я Вам отвечу вот что:



По идеи надо писать так:

if Index<=1 then
begin
Result:=1;
exit;
end;

А то при вводе 0 или отрицательного функция уйдет в себя, да и про то,
что 0!=1 забыли

Афоризм напоследок: Столько дел, что и работой занятся некогда...
Winamp глаголит: Billy More - Up And Down(Don't Fall In Lov With Me)
11 апреля 2005 г. 19:57:53

Просто студент
Eugene mailto:rav***@o*****.ru

Номер выпуска : 4308
Возраст листа : 568 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/349023
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Mon, 11 Apr 2005 20:00:49 +0400 (#349023)

 

...::: Приветствую, Eugene the M@NSTER :::...

Если писать как ты говоришь то сразу будет exit

= = = = = = = = = = = = = = = = = = = =
..::: by GENEMI :::...

Номер выпуска : 4366
Возраст листа : 572 (дней)
Количество подписчиков : 516
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/351564
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Thu, 14 Apr 2005 14:08:00 +0300 (#351564)

 

Привет GENEMI,

Вы мне письмо написали 14 апреля 2005 г. (четверг), а я Вам отвечу вот что:

А если Index будет больше 1, то ...! Догадайся сам.
Похорошему тут надо делать проверку на то, что
1) число не отрицательное, т.к. факториал отрицательного числа не
существует (или я не знаю как его посчитать - в справочнике по ВышМату
видел формулу, которая позволяет посчитать факториал, даже от дробного
не отрицательного числа)
2) 0!=1
3) 1!=1
Если не одно из условий 1)-3) не выполняется, то N!=N*(N-1)!

Так вот условия 1)-2) в первоначальном варианте не проверяются.
Попробуй запустить функцию с N<=0 - получишь переполнение стека.

P.S. В моем варианте условие 1) выполняется не полно: если N<0, то
N!=1

Афоризм напоследок: Щедрость философия бедноты.
Winamp глаголит: Король и Шут - Собрание
16 апреля 2005 г. 19:38:53

Просто студент
Eugene mailto:rav***@o*****.ru

Номер выпуска : 4370
Возраст листа : 573 (дней)
Количество подписчиков : 517
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/352327
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sat, 16 Apr 2005 19:47:42 +0400 (#352327)