Форум русскоязычного сообщества Ubuntu


Следите за новостями русскоязычного сообщества Ubuntu в Twitter-ленте @ubuntu_ru_loco

Автор Тема: Программа на си  (Прочитано 3755 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн peregrine

  • FSM
  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 7215
  • Gentoo x64 Ubuntu 16.04.1 x64
    • Просмотр профиля
Re: Программа на си
« Ответ #30 : 16 Сентября 2014, 01:16:10 »
unimix, по результату (сферическому в вакууме) - да, а по логике работы - нет.

Оффлайн .ubuntufan

  • Активист
  • *
  • Сообщений: 638
    • Просмотр профиля
Re: Программа на си
« Ответ #31 : 16 Сентября 2014, 01:40:52 »
peregrine

И по результату и по логике - да.
В некоторых языках - Haskell, Erlang и т.д. рекурсия полностью заменяет циклы.


Оффлайн peregrine

  • FSM
  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 7215
  • Gentoo x64 Ubuntu 16.04.1 x64
    • Просмотр профиля
Re: Программа на си
« Ответ #32 : 16 Сентября 2014, 01:55:18 »
.ubuntufan, нет, в общем случае рекурсия пользуется стеком, а он не бесконечен, а весьма и весьма мал, потому рекурсию в классических языках лучше не использовать. Хвостовая рекурсия это частный вид рекурсии, который оптимизируется компилятором до итерации.

Оффлайн .ubuntufan

  • Активист
  • *
  • Сообщений: 638
    • Просмотр профиля
Re: Программа на си
« Ответ #33 : 16 Сентября 2014, 02:08:09 »
Если только про C разговор то да. Если нет то

Цитировать
Хвостовая рекурсия это частный вид рекурсии, который оптимизируется компилятором до итерации.

Чем не цикл?

Оффлайн Protopopulus

  • Старожил
  • *
  • Сообщений: 1695
  • А чего вы так смотрите?..
    • Просмотр профиля
Re: Программа на си
« Ответ #34 : 16 Сентября 2014, 02:55:27 »
Если только про C разговор то да. Если нет то
...
Чем не цикл?
Логикой работы:
Цикл:
movq $100, %rcx // i = 100;

begin:
cmpq $0,   %rcx // i == 0 ?
je   stop       // если итератор == 0, то завершить цикл
...
...             // тело цикла
...
subq $1,   %rcx // --i
jmp  begin      // к началу цикла

stop:
...             // инструкции программы

Рекурсия:
function:
push %rbp       // преамбула функции,
movq %rsp, %rbp // в которой запихивается
                // в стек 4 (х32) или 8 (х64) байта
...
...             // тело функции
...

jmp  function   // рекурсивный вызов

movq %rbp, %rsp // эпилогфункции,
pop  %rbp       // в котором извлекается из стека
                // 4-8 байт (см. выше).
                // Но из-за рекурсии, извлекается
                // только после завершения функции
ret             // банальный return в тело программы
Вроде бы, так записал. Давно ассемблером не занимался...

UPD: Многие компиляторы зачастую преобразуют рекурсивные функции, если могут, конечно, в циклы, дабы, в ходе выполнения, не кончился вдруг стек.
« Последнее редактирование: 16 Сентября 2014, 02:58:46 от Protopopulus »
Если ты владеешь знаниями, то и знания владеют тобой. (с) Protopopulus

Оффлайн .ubuntufan

  • Активист
  • *
  • Сообщений: 638
    • Просмотр профиля
Re: Программа на си
« Ответ #35 : 16 Сентября 2014, 03:50:38 »
Protopopulus

То что вы описали - рекурсия обыкновенная а речь о хвостовой рекурсии в таких языках как Haskell, Erlang, etc. когда вместо создания фрейма в стеке, происходит замена аргументов и прыжок к определению функции.

http://it.kgsu.ru/Prolog/pro040.html
« Последнее редактирование: 16 Сентября 2014, 03:53:46 от .ubuntufan »

Оффлайн Protopopulus

  • Старожил
  • *
  • Сообщений: 1695
  • А чего вы так смотрите?..
    • Просмотр профиля
Re: Программа на си
« Ответ #36 : 16 Сентября 2014, 08:07:30 »
.ubuntufan, ну ладно, не велика разница. Рекурсия - это рекурсия - это рекурсия - это рекурсия - это... :D А так-то да, по сути,  любая рекурсивная функция, в том числе и на Си, может быть представлена эквивалентной реализацией посредством цикла, т.е.:
begin:
cmp $1, %rcx // проверка флага завершения
je  stop
...
...          // тело цикла
...
mov $1, %rcx // установка флага завершения
...
jmp begin
stop:
...
« Последнее редактирование: 16 Сентября 2014, 08:19:57 от Protopopulus »
Если ты владеешь знаниями, то и знания владеют тобой. (с) Protopopulus

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Программа на си
« Ответ #37 : 16 Сентября 2014, 10:33:34 »
Рекурсивная функция имеет ограничение, накладные расходы и внезапность прерывания, но она предоставляет удобный способ организации циклов с возможностью создания своих переменных на каждую итерацию, а также возможностью использования данных от следующих итераций (не хвостовая рекурсия). Обход дерева небольшой глубины с изменением узлов может превратиться в тот же цикл, но с реализацией своего стека.

Да и не всегда же цикл должен быть бесконечным.

« Последнее редактирование: 16 Сентября 2014, 10:36:21 от unimix »

Оффлайн Delit

  • Новичок
  • *
  • Сообщений: 18
    • Просмотр профиля
Re: Программа на си
« Ответ #38 : 16 Сентября 2014, 10:36:48 »
А по моему изначальный код выглядит и читается проще чем код с циклом.

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12141
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Re: Программа на си
« Ответ #39 : 16 Сентября 2014, 11:05:36 »
Delit, позволю принципиально не согласится:

Конструкция типа:

метка 1:
если <условие> то переход метка 2
...
...
переход метка 1

выглядит гораздо более громоздко чем

пока <условие> выполнять {
...
... }

... не говоря уже о том что заводятся дополнительные два идентификатора меток. В большом объеме кода - чем меньше идентификаторов тем меньше шансов в них запутаться. Именно поэтому есть много сторонников отказа от goto в языках программирования более высокого уровня чем ассемблер.

Многие, правда, возражают что тот же фортран ...... но забывают, что фортран, по сути, - макро-ассемблер.
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12141
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Re: Программа на си
« Ответ #40 : 16 Сентября 2014, 11:10:37 »
unimix, вот зря вы тут рекурсию приплели.

Рекурсия сама по себе оправдана в очень узком круге задач (часто чисто академических). В прикладных задачах для рекурсии практически не сыскать применения ИМХО. А по ресурсоёмкости рекурсия вообще запредельная при реализации на языках высокого уровня . Не всегда оптимизатор кода может сделать приличную по потребляемым ресурсам рекурсию, а уж если язык интерпретируемый - то там и вообще все очень плохо...
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Delit

  • Новичок
  • *
  • Сообщений: 18
    • Просмотр профиля
Re: Программа на си
« Ответ #41 : 16 Сентября 2014, 11:50:26 »

метка 1:
...
...
если <условие> то переход метка 1



выглядит боле естественно чем

{
...
...
} пока <условие> выполнять

мне кажется что циклы не должны управлять логикой программы

Оффлайн unimix

  • Активист
  • *
  • Сообщений: 537
    • Просмотр профиля
Re: Программа на си
« Ответ #42 : 16 Сентября 2014, 12:01:46 »
Sly_tom_cat, прикладные задачи -- это какие? Вот если мне надо построить дерево из XML файла, или вывести иерархию репозитория, или пройтись по структуре файлов, то всегда выкручиваться простыми циклами со своими стеками?

Я конечно люблю делать сложные циклы, но иногда легче запустить рекурсивные функции или объекты, которые работают по тому же принципу.
« Последнее редактирование: 16 Сентября 2014, 12:07:37 от unimix »

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12141
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Re: Программа на си
« Ответ #43 : 16 Сентября 2014, 12:11:50 »
Delit, в начальном коде был цикл while-do, а не описанный вами цикл do-until/do-while. Именно while-do-цикл требует два перехода (условный и безусловный), и именно он выглядит гораздо внятнее в цикловой записи, а не в goto-шной.

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


unimix, так я же не говорил никогда/нигде и т.п. крайности. Я сказал, что задачи прикладного плана редко требуют рекурсивных решений. Пример с XML - это один из тех случаев когда да - оно нужно.
« Последнее редактирование: 16 Сентября 2014, 12:16:08 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн peregrine

  • FSM
  • СуперМодератор
  • Старожил
  • *
  • Сообщений: 7215
  • Gentoo x64 Ubuntu 16.04.1 x64
    • Просмотр профиля
Re: Программа на си
« Ответ #44 : 16 Сентября 2014, 15:51:14 »
Protopopulus, далеко не любая рекурсия может быть представлена циклом (иногда может быть очень сложно, а то и невозможно).
Delit, когда кажется, креститься надо. Циклы рулят и педалят.

 

Страница сгенерирована за 0.033 секунд. Запросов: 25.