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

Понятие рекурсии и её виды. Общие принципы ее программной реализации. Выбор языка программирования для реализации алгоритма. Схема механизма вызова функции в аппаратном стеке. Блок-схема нахождения факториала числа. Метод Фибоначчи JAVA и его отладка.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 19.01.2019
Размер файла 2,3 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

Тема: Рекурсивный алгоритм вычисления натуральной степени числа

Обучающийся: Тербердеев Александр Сергеевич, группа: АТПбзу-15

Содержание

  • Введение
    • 1. Теория рекурсивных алгоритмов
      • 1.1 Понятие рекурсии и её виды
        • 1.2 Общие принципы программной реализации рекурсии
          • 2. Разработка структурной схемы программного продукта
          • 2.1 Выбор языка программирования для реализации алгоритма

2.2 Алгоритм программы

2.3 Реализация алгоритма

2.4 Сравнительные характеристики

  • 3. Реализация методов рекурсии
    • 3.1 Рекурсивный метод в JAVA
      • 3.2 Метод Фибоначчи JAVA
        • 3.3 Рекурсивный метод Массив JAVA
          • 3.4 Отладка метода Фибоначчи
          • 3.5 Отладка программы JAVA под систему
        • Заключение
        • Список литературы
        • Введение

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

Для решения проблем такого рода, особенно при учёте человеческого фактора, возникает необходимость обеспечения понятности алгоритма, так называемой «читабельности» исходного кода программы, и как следствие модифицируемости и относительной лёгкости сопровождения конечного программного продукта. Часто этого можно достигнуть включением в реализацию приложения рекурсивных подпрограмм, механизмы использования которых предоставляются практически всеми современными компиляторами и средами разработки.

В настоящее время область практического применения рекурсии весьма широка. Она включает, в частности, сложные задачи численного анализа, алгоритмы трансляции, а также различные операции над списками, являющиеся необходимым аппаратом разработки современных автоматизированных систем управления. Поэтому аппарат рекурсии предусматривается практически во всех языках программирования, появляющихся после АЛГОЛа.

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

Тьюринга: американский специалист по системному программированию Д.Кнут и английский теоретик информатики Ч.Хоар.

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

1. Теория рекурсивных алгоритмов

Рекурсия - метод определения класса объектов или методов предварительным заданием одного или нескольких (обычно простых) его базовых случаев или методов, а затем заданием на их основе правила построения определяемого класса, ссылающегося прямо или косвенно на эти базовые случаи.

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

Рекурсивный алгоритм (процедура, функция):

-алгоритм называется рекурсивным, если в его определении содержится прямой или косвенный вызов этого же алгоритма;

-рекурсивная функция - одно из математических уточнений интуитивного понятия вычислимой функции.

1.1 Понятие рекурсии и её виды

Адаптивный рекурсивный алгоритм - алгоритм, который благодаря рекурсивности учитывает те или иные индивидуальные характеристики решаемой задачи из области своего определения.

Базис рекурсии - это предложение, определяющее некую начальную ситуацию или ситуацию в момент прекращения. Как правило, в этом предложении записывается некий простейший случай, при котором ответ получается сразу, даже без использования рекурсии.

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

Основное правило рекурсии: до рекурсивного вызова должна стоять проверка на возврат из рекурсии. Существуют следующие виды рекурсии:

-прямая рекурсия - непосредственный вызов алгоритма (функции, процедуры, метода) из текста самого метода.

В данном случае функция r1( ) вызывает саму себя.

#include <iostream>

using namespace std;

void r1 (int a);

void r2 (int a);

void r3 (int a);

void r1(int a)

{

cout << "function r1" << endl;

if (a < 6)

r1(a+1);

}

int main ( )

{

r1 (0);

return NULL;

}

Результат работы программы представлен на рисунке 1.1.

Рисунок 1.1 - Прямая рекурсия

-косвенная рекурсия.

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

В данном случае функция r1( ) вызывает функцию r2( ), которая вызывает r3( ).

Функция r3( ) в свою очередь снова вызывает r1( ).

#include <iostream>

using namespace std;

void r1 (int a);

void r2 (int a);

void r3 (int a);

void r1(int a)

{

cout << "function r1" << endl;

if (a < 6)

r2(a+1);

}

void r2(int a)

{

cout << "function r2" << endl;

if (a < 6)

r3(a+1);

}

void r3(int a)

{

cout << "function r3" << endl;

if (a < 6)

r1(a+1);

}

int main ( )

{

r1 (0);

return NULL;

}

Результат работы программы представлен на рисунке 1.2.

Рисунок 1.2 - Косвенная рекурсия

-линейная рекурсия - если исполнение подпрограммы приводит только к одному вызову этой же самой подпрограммы, то такая рекурсия называется линейной.

Рисунок 1.3 - Линейная рекурсия

#include <iostream>

using namespace std;

void function(int a);

void function (int a)

{

if (a > 0)

function(a - 1);

}

int main ( )

{

function(3);

return NULL;

}

-ветвящаяся рекурсия - если каждый экземпляр подпрограммы может вызвать себя несколько раз, то рекурсия называется нелинейной или "ветвящейся".

Рисунок 1.4 - Ветвящаяся рекурсия

#include <iostream>

using namespace std;

int function(int a);

int function (int a)

{

if (a > 3)

a = function (a - 1) * function(a - 2);

return a;

}

int main ()

{

cout << function(6) << endl;

return NULL;

}

-бесконечная рекурсия (на самом деле это условное обозначение так как при переполнении памяти компьютера программа выдаст ошибку и/или завершит ее в аварийном режиме).

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

Например:

void function ()

{ function(); }

Другой пример:

int Function (unsigned int n)

// Unsigned int - тип, содержащий неотрицательные значения

{ if (n > 0)

{

Function(n++); return n;

}

else return 0;

}

Результат работы программы представлен на рисунке 1.5.

Рисунок 1.5 - Сообщение о переполнении стека

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

1.2 Общие принципы программной реализации рекурсии

В программировании рекурсия - вызов функции (процедуры) из неё же самой, непосредственно (простая рекурсия) или через другие функции (сложная рекурсия), например, функция A вызывает функцию B, а функция B - функцию A. Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.

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

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

Имеется специальный тип рекурсии, называемый «хвостовой рекурсией». Интерпретаторы и компиляторы функциональных языков программирования, поддерживающие оптимизацию кода (исходного и/или исполняемого), автоматически преобразуют хвостовую рекурсию к итерации,

благодаря чему обеспечивают выполнение алгоритмов с хвостовой рекурсией в ограниченном объёме памяти. Такие рекурсивные вычисления, даже если они формально бесконечны (например, когда с помощью рекурсии организуется работа командного интерпретатора, принимающего команды пользователя), никогда не приводят к исчерпанию памяти.

Нужно учитывать одну особенность, характерную для рекурсивных программ, подобных той, которую используют для генерации чисел Фибоначчи. Каждый уровень рекурсии в функции fibonacci удваивает количество вызовов, так что количество рекурсивных вызовов, которое должно быть выполнено для вычисления n - го числа Фибоначчи, оказывается порядка 2N.

Объем вычислений резко нарастает с увеличением n. Вычисление только 20 - го числа Фибоначчи потребовало бы порядка 2N или около миллиона вызовов, вычисление 30 - го числа Фибоначчи потребовало бы порядка 3N или около миллиарда вызовов и так далее. В методах вычислений это называется экспоненциальной сложностью.

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

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

Другая причина предпочтения рекурсивного решения состоит в том, что итеративное решение может не быть очевидным.

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

Стек - связная структура данных, построенная на принципе «первый пришёл - первый вышел» (Fiгst In - Fiгst Out, FIFO). То есть вновь добавляемые объекты помещаются в начало, вершину стека, и выбираются они также только из вершины.

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

При завершении B управление должно возвращаться в A, в точку, следующую за вызовом B. Правильную последовательность возвратов легко обеспечить, если при каждом вызове процедуры записывать адрес возврата в стек. Так, когда процедура A вызывает процедуру B, в стек заносится адрес возврата в A; когда B вызывает C, в стек заносится адрес возврата в B.

Когда C заканчивается, адрес возврата выбирается из вершины стека - а это адрес возврата в B. Когда заканчивается B, в вершине стека находится адрес возврата в A, и возврат из B произойдет в A.

Механизм вызова функции или процедуры в языке высокого уровня существенно зависит от архитектуры компьютера и операционной системы. В рамках IBM PC совместимых компьютеров, в микропроцессорах семейства

Intel, как и в большинстве современных процессорных архитектур, поддерживается аппаратный стек.

Аппаратный стек расположен в ОЗУ, указатель стека содержится в паре специальных регистров SS:SP доступных для программиста. Аппаратный стек расширяется в сторону уменьшения адресов, указатель его адресует первый свободный элемент. Схематично этот механизм иллюстрирован на рисунке 1.6.

Языки PASCAL, C, C++ используют стек для размещения в нем локальных переменных процедур и иных программных блоков. Стек разбит на фрагменты, представляющие собой блоки последовательных ячеек.

Рисунок 1.6 - Механизм вызова функции в аппаратном стеке

Каждый вызов подпрограммы использует фрагмент стека, длина которого зависит от вызывающей подпрограммы. При каждой активизации процедуры память для ее локальных переменных выделяется в стеке; при завершении процедуры эта память освобождается. Поскольку при вызовах процедур всегда строго соблюдается вложенность, то в вершине стека всегда находится память, содержащая локальные переменные активной в данный момент процедуры.

Таким образом, в общем случае при вызове процедурой A процедуры B происходит следующее:

1. В вершину стека помещается фрагмент нужного размера. В него входят следующие данные:

а) указатели фактических параметров вызова процедуры В;

б) пустые ячейки для локальных переменных, определенных в процедуре В;

в) адрес возврата, т.е. адрес команды в процедуре A, которую следует выполнить после того, как процедура B закончит свою работу.

Если B - функция, то во фрагмент стека для B помещается указатель ячейки во фрагменте стека для A, в которую надлежит поместить значение этой функции (адрес значения).

2. Управление передается первому оператору процедуры B.

3. При завершении работы процедуры B управление передается процедуре A с помощью следующей последовательности шагов:

а) адрес возврата извлекается из вершины стека;

б) если B - функция, то ее значение запоминается в ячейке, предписанной указателем на адрес значения;

в) фрагмент стека процедуры B извлекается из стека, в вершину ставится фрагмент процедуры A;

г) выполнение процедуры A возобновляется с команды, указанной в адресе возврата.

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

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

Рекурсия использует стек в скрытом от программиста виде, но все рекурсивные процедуры могут быть реализованы и без рекурсии, но с явным использованием стека.

Рассмотрим пример для функции вычисления факториала: дерево рекурсии при вычислении 5! (рисунок 1.7).

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

Рисунок 1.7 - Дерево рекурсии при вычислении факториала числа 5

Рисунок 1.8 - вычисление 5ого числа Фибоначчи (Fb(5)).

Упомянутый анализ практической сложности программ показывает, что часто асимптотически более сложные итеративные алгоритмы, на практике становятся более эффективными.

Сравнивая скорость вычисления чисел Фибоначчи с помощью итеративной и рекурсивной функции можно заметить, что итеративная функция выполняется почти «мгновенно», не зависимо от значения n. При использовании же рекурсивной функции уже при n=40 заметна задержка при вычислении, а при больших n результат появляется весьма не скоро. Причина, как уже было сказано, кроется в том, что в теории не учтена зависимость времени работы программы от количества вызовов вложенных подпрограмм. Неэффективность рекурсии проявляется в том, что одни и те же вычисления производятся много раз. Особенно сильно это проявляется в методе, который был самым востребованным при построении теоретически быстрых рекурсивных алгоритмов, - методе бинарного разбиения на независимые подзадачи. Когда подзадачи независимы, это часто приводит к недопустимо большим затратам времени, так как одни и те же подзадачи решаются многократно.

Обходить подобные ситуации позволяет подход, известный как динамическое программирование. Этот подход для реализации рекурсивных программ дает возможность получать эффективные и элегантные решения для обширного класса задач.

Технология, называемая восходящим динамическим программированием (bottom - up dynamic pгogгamming) основана на том, что значение рекурсивной функции можно определить, вычисляя все значения этой функции, начиная с наименьшего, используя на каждом шаге ранее вычисленные значения для подсчета текущего значения. Она применима к любому рекурсивному вычислению при условии, что мы можем позволить себе хранить все ранее вычисленные значения. Это в результате позволит уменьшить временную зависимость с экспоненциальной на линейную.

Нисходящее динамическое программирование (top - down dynamic pгogгamming). Оно позволяет выполнять рекурсивные функции при том же количестве итераций, что и восходящее динамическое программирование. Технология требует введения в рекурсивную программу неких средств, обеспечивающих сохранение каждого вычисленного значения и проверку сохраненных значений во избежание их повторного вычисления.

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

- часто это наиболее легкий метод написания алгоритма для задач, которые можно решить с помощью рекурсии (число фибоначчи, факториал);

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

- целый ряд структур данных и многие объекты современных языков программирования рекурсивны по самой своей сути (фрактальные объекты, иерархия классов в объектно-ориентированном программировании, древовидные регулярные структуры данных) и программы для работы с такими структурами выглядят намного более естественно в рекурсивной реализации;

- рекурсия делает код более читабельным (позволяет читать код с любого места, не просматривая его весь, отслеживая все изменения переменной), что облегчает отладку;

- рекурсия защищает от ошибок типа: «действия выполнены в неверном порядке», «использована неинициализированная переменная» и других аналогичных.

Недостатки рекурсии заключаются в следующем:

- велика возможность войти в бесконечный цикл;

- при использовании некоторых формул слишком большие затраты памяти компьютера (к примеру, при вычислении числа Фибоначчи или факториалов, необходимо запоминать все значения чисел и вычислять одни и те же значения по многу раз);

- в случае если вызываемых функций будет очень много, может произойти переполнение стека;

- следует избегать использования рекурсии в случаях, когда требуется высокая эффективность, так как они требуют времени и дополнительных затрат памяти и обладают худшей временной эффективностью.

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

рекурсия алгоритм факториал число

2. Разработка структурной схемы программы

2.1 Выбор языка программирования для реализации алгоритма

C++ - компилируемый статически типизированный язык программирования общего назначения.

Поддерживает такие парадигмы программирования как процедурное программирование, объектно-ориентированное программирование, обобщённое программирование, обеспечивает модульность, раздельную компиляцию, обработку исключений, абстракцию данных, объявление типов (классов) объектов, виртуальные функции. Стандартная библиотека включает, в том числе, общеупотребительные контейнеры и алгоритмы. C++ сочетает свойства как высокоуровневых, так инизкоуровневых языков. В сравнении с его предшественником-- языком C,-- наибольшее внимание уделено поддержке объектно-ориентированного и обобщённого программирования.

C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений (игр). Существует множество реализаций языка C++, как бесплатных, так и коммерческих и для различных платформ. Например, на платформе x86 это GCC, Visual C++, Intel C++ Compiler, Embarcadero (Borland) C++ Builderи другие. C++ оказал огромное влияние на другие языки программирования, в первую очередь на Java и C#.

Синтаксис C++ унаследован от языка C. Одним из принципов разработки было сохранение совместимости с C. Тем не менее, C++ не является в строгом смысле надмножеством C; множество программ, которые могут одинаково успешно транслироваться как компиляторами C, так и компиляторами C++, довольно велико, но не включает все возможные программы на C.

Язык Паскаль был создан Никлаусом Виртом в 1968--1969 годах после его участия в работе комитета разработки стандарта языкаАлгол-68. Язык назван в честь французского математика, физика, литератора и философа Блеза Паскаля, который создал первую в мире механическую машину, складывающую два числа. Первая публикация Вирта о языке датирована 1970 годом, представляя язык, автор указывал в качестве цели его создания -- построение небольшого и эффективного языка, способствующего хорошему стилю программирования, использующему структурное программирование и структурированные данные.

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

2.2 Алгоритм программы

Факториамл числа n (лат. Factorialis -- действующий, производящий, умножающий; обозначается n!, произносится эн факториамл) -- произведение всех натуральных чисел от 1 до n включительно.

2.3 Реализация алгоритма

Задача 1. Числа Фибоначчи.

Рекурсия аналогична методу математической индукции. Базе индукции соответствует база рекурсии. Предположению индукции соответствует предположение о том, что нужная процедура уже написана. Шагу индукции соответствует вызов создаваемой рекурсивной процедуры. В любой рекурсии необходимо предусмотреть условие завершения процесса, т.е. когда вызова больше не происходит.

Рисунок 2.1 - Блок-схема нахождения факториала числа

Рассмотрим - вычисление N - ого по счёту числа Фибоначчи. Числа Фибоначчи составляют последовательность, очередной элемент которой вычисляется по двум предыдущим значениям:

Язык С++.

Fn=Fn - 1 + Fn - 2 .

#include <iostream>

int fib(int n) {

if(n < 3)

return 1;

return fib(n - 2) + fib(n - 1);

}

int main() {

int n = 0;

std::cout << "Vvedite nomer chisla:\n";

std::cin >> n;

std::cout << "Result: chislo " << fib(n) << " eto " << n << "th po schetu chislo v ryade Fibonacci.\n";

return 0;

}

Результат работы программы представлен на рисунке 2.2

Рисунок 2.2 - Числа Фибоначчи

Язык Паскаль.

var

a,b,c,i,n: integer;

begin

write('n = ');

readln(n);

a := 0;

write(a,' ');

b := 1;

write(b,' ');

for i:=3 to n do begin

write(a+b,' ');

c := b;

b := a + b;

a := c

end;

readln

end.

Задача 2. Нахождение факториала.

Язык С++.

#include <iostream>

int factorial(int n)

{

if(n==1 || n==0) return 1;

return n* factoгial (n - 1);

}

int main() {

int n = 0;

std::cout << "Vvedite chislo:\n";

std::cin >> n;

std::cout << "Factorial " << n << " raven " << factorial(n) << "\n";

return 0;

}

Язык Паскаль.

program fac;

function f(n: byte): real;

begin

if n > 1 then result := f(n - 1) * n

else result := 1

end;

var

n: byte;

begin

write('n = ');

readln(n);

writeln(f(n))

end.

Результат работы программы представлен на рисунке 2.3

Рисунок 2.3 - Факториал числа

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

2.4 Сравнительные характеристики

Рисунок 2.4 - Среднее значение времени работы в миллисекундах.

Паскаль - этот язык наиболее распространен, имеет следующие достоинства:

1) относительная простота (т.к. разрабатывался с целью обучения программированию);

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

3) гибкие возможности в отношении используемых структур данных;

4) высокая эффективность программ;

5) наличие средств повышения надежности программ, включающих контроль правильности использования данных различных типов и программных элементов на этапах трансляции, редактирования и выполнения.

Недостатки:

1. Сравнительно громоздкие конструкции языка.

2. Ограниченная библиотека ввода-вывода.

3. отсутствие средств для подключения функций написанных на других языках;

C++ -- чрезвычайно мощный язык, содержащий средства создания эффективных программ практически любого назначения, от низкоуровневых утилит и драйверов до сложных программных комплексов самого различного назначения.

Рисунок 2.5 - График с линейной шкалой

Достоинства:

1. Поддерживаются различные стили и технологии программирования, включая традиционное директивное программирование, ООП, обобщённое программирование, метапрограммирование (шаблоны, макросы).

2. Язык поддерживает понятия физической (const) и логической (mutable) константности. Это делает программу надёжнее, так как позволяет компилятору, например, диагностировать ошибочные попытки изменения значения переменной. Объявление константности даёт программисту, читающему текст программы дополнительное представление о правильном использовании классов и функций, а также может являться подсказкой для оптимизации. Перегрузка функций-членов по признаку константности позволяет определять изнутри объекта цели вызова метода (константный для чтения, неконстантный для изменения). Объявление mutable позволяет сохранять логическую константность при использовании кэшей и ленивых вычислений.

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

Недостатки:

1. Макросы (#define) являются мощным, но опасным средством. Они сохранены в C++ несмотря на то, что необходимость в них, благодаря шаблонам и встроенным функциям, не так уж велика. В унаследованных стандартных Си-библиотеках много потенциально опасных макросов.

2. Некоторые преобразования типов неинтуитивны. В частности, операция над беззнаковым и знаковым числами выдаёт беззнаковый результат.

3. Сложность и избыточность, из-за которых C++ трудно изучать, а построение компилятора сопряжено с большим количеством проблем.

Рисунок 2.6 - График с логарифмической шкалой

3. Реализация методов рекурсии

3.1 Рекурсивный метод на языке JAVA

Отдельно рассмотрим рекурсивные функции. Главное отличие рекурсивных функций от обычных состоит в том, что они рекурсивная функция может вызывать саму себя.

Вычислить факториал n! через рекурсию можно при помощи выражения n*(n-1) Что касается примера ниже, из новшеств отмечу тип long. Это, как и int, целочисленный тип, но типу int требуется 4 байта памяти, а типу long 8.

Само собой, что и диапазон у long больше: int: от-2 147 483 648до2 147 483 647включительно long: от-9 223 372 036 854 775 808до9 223 372 036 854 775 807включительно;

Пример:

package Recursion;

public class Main {

public static int fact (int n) {

if (n == 1) return 1;

if (n == 2) return 2;

return fact (n-1) * n;

}

public static void main (String[] args) {

// Рекурсия

Int res = fact (4);

System.out.println ("res = " + res);

res = 24 (ответ)

Рисунок 2.7 - Рекурсивный метод вызов себя

3.2 Метод Фибоначчи на языке JAVA

Числа Фибоначчи -- числовая последовательность, первые два элемента которой равны 1, а каждый последующий равен сумме двух предыдущих.

Вывод программы должен выглядеть следующим образом: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, …

Отметим, что данный пример может быть реализован несколькими способами:

· непосредственно через рекурсивное определение: наименее эффективный способ, позволяющий в то же время продемонстрировать использование рекурсивных функций.

· с сохранением вычисленных чисел в массиве: более эффективный способ, позволяющий продемонстрировать работу с массивами.

· черезформулу Бине: наиболее эффективный способ, позволяющий продемонстрировать работу с математическими функциями.

Пример:

public static int fibonachi (int n) {

if ( (n == 1) (n == 2)) return 1;

return fibonachi (n-1) + fibonachi (n-2);

}

public static voild main (String[] args) {

// Рекурсия

for (int i = I; i <= 10; i++) {

int res = fibonachi (i);

System.out.println ("res = " + res);

}

Рисунок 2.8 - Метод Фибоначчи последовательность чисел

3.3 Метод Массив на языке JAVA

Есть две проблемы, которые отличают массивы от других типов контейнеров: эффективность и тип. Массив является наиболее эффективным способом, из тех, которые обеспечивает Java, для хранения объектов и доступа к ним в случайном порядке (на самом деле, речь идет о ссылках на объекты). Массив - это простая линейная последовательность, которая делает быстрым доступ к элементам, но вы расплачиваетесь за эту скорость: когда вы создаете массив объектов, его размер фиксирован и не может изменяться в течение всей продолжительности жизни этого массива объектов. Вы можете согласиться создать массив определенного размера, а затем, если вы выйдите за пределы, создадите новый и переместите все ссылки из старого массива в новый. Однако, потому что превышение этого размера не всегда одинаково, Array List менее эффективен, чем массив.

Контейнерный класс vector в C++ знает тип объектов, которые он хранит, но он имеет другие недостатки по сравнению с массивами в Java:

Метод vector'а из С++operator [] не делает проверки границ, так что вы можете выйти за пределы. В Java есть проверка границ не зависимо от того используете ли вы массив или контейнер, вы получите Runtime Exception, если вы выйдите за границы. Этот тип исключения указывает на ошибку программы, и поэтому у вас нет необходимости выполнять проверку в вашем коде. С другой стороны, объяснением того, что vector из С++ не проверяет границы при каждом доступе, может стать скорость доступа, в Java вы имеете постоянную проверку на превышение пределов все время и для массивов и для контейнеров.

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

Пример:

public class A {

private int [] mas;

public A (int n) {

mas = new int [n];

for (int I = 0; i < mas. length; i++) {

mas[i] = (int) Math.round ( (Math.random( ) * 100) );

}

}

public void print (int n) {

if (n == 0) return;

System. out. println (mas [n-1] + " " );

print (n-1);

}

public class Main {

public static void main (String[] args) {

// Рекурсия

A a = new A(10);

a.print (10);

}

}

Рисунок 2.9 - Рекурсивный метод Массив

3.4 Отладка метода Фибоначчи

Небольшая неточность в числах Фибоначчи. Ряд должен начинаться с 0, а не с 1, т.е. функция fibonachi(1) должна вернуть 0 а не 1. Можно исправить следующим образом:

public static int fibonachi (int n){

if(n == 1) { return 0 ;}

if (n == 2) { return 1 ;}

else return fibonachi ( n - 2 )+fibonachi ( n - 1 );

}

И получаем желаемый результат числа Фибоначчи от 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, … и так далее.

3.5 Отладка программы JAVA под систему

Java как и любая программа вашего ПК должна соответствовать разрядности вашего Windows , только тогда она способна без конфликта работать с другими программами и вашей ОЗУ. Как это сделать?

Пример:

Данная отладка представлена на программе Java (x64) и ОЗУ 8гб.

Если ваша система такова следуем данной инструкции.

1) Пуск - Панель Управления, находим программу Java и кликнем на нее.

2) Выходит Java Control Panel далее кликнем на вкладку General.

3) Далее в данном окне находим кнопку Settings заходим в нее.

4) Выставляем количество мегабайт до значения 32768 и Select the compression level for JAR fiels: ставим Medium и кликнем OK.

Рисунок 2.10 - Настройка ОЗУ для программы JAVA

5) Далее заходим в раздел JAVE кликнем по кнопке View…

6) Во вкладке User в закладке Runtimes Parameters выставляем ваше значение ОЗУ (например если это 4гб значение будет таково 3072м-4096м; или как у меня 8гб то повышение пойдет так 6144м-8196м и кликнем Ok.

Рисунок 2.11 - Выставление ОЗУ для программы JAVA

Заключение

На основании проведенного исследования можно сделать несколько выводов:

- во-первых, рекурсивные алгоритмы есть универсальное средство решения разнообразных алгоритмических проблем. Любая разрешимая задача такого рода имеет рекурсивное решение, которое при этом отличается изяществом и простотой для восприятия человеком;

- во-вторых, рекурсивные алгоритмы часто имеют более низкую асимптотическую сложность, чем эквивалентные им итерационные. То есть теоретически они быстрее;

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

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

Сравнив, можно сделать вывод: Паскаль более структурирован и типизирован. С++ более гибок и соответственно более труден для восприятия чужого текста программы.

Список используемой литературы

1. Литература обязательная

1. C/C++. Программирование на языке высокого уровня / Т. А. Павловская. - СПб.: Питер, 2003. - 461 с: ил.

2. Головешкин В.А., Ульянов М. В. Теория рекурсии для программистов. М.: ФИЗМАТЛИТ, 2006. 296 с.

3. Харви Дейтел и Пол Дейтел Как программировать на C++. Бином, 2006.

4. Громов Ю.Ю., Татаренко С.И. Языки СИ и С++ для решения инженерных и экономических задач. Тамбов: Издательство ТГТУ, 2001.

2. Литература дополнительная

5. Давыдов В.Г. Программирование и основы алгоритмизации: учеб. пособие. - М.: Высш. шк., 2003. - 447 с.

6. Сухарев М. Delphi. Полное руководство. Включая версию 2010. - СПб.: Наука и техника, 2010. - 1035 с.

7. Истомин Е.П. Программирование на языках высокого уровня: учеб/ Е.П. Истомин, С.Ю. Неклюдов. - СПб: Изд-во Михайлова В.А., 2003. - 719 с.

8. Вальвачев А.Н. и др. Программирование на языке Delphi. Глава 9. Окна диалога.

3. Интернет ресурсы

9. ЭВМ. Программирование.

10. JAVA руководство пользователя.

11. JAVA методы пользования, учебник программирования

12. Уроки программирования

13. Языки программирования

14. Введение в программирование

15. Видео-уроки по JAVA

Размещено на Allbest.ru

...

Подобные документы

  • Обратная трассировка лучей: ограничения при реализации, достоинства и недостатки. Математические и физические предпосылки алгоритма, блок-схема. Выбор языка программирования. Зависимость времени генерации от глубины рекурсии, количества источников.

    курсовая работа [503,0 K], добавлен 27.05.2013

  • Элементы и переменные, используемые для составления записи в Паскале. Основные числовые типы языка Turbo Pascal. Составление блок-схемы приложения, программирование по ней программы для вычисления функции. Последовательность выполнения алгоритма.

    лабораторная работа [256,9 K], добавлен 10.11.2015

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

    реферат [155,9 K], добавлен 19.10.2013

  • Применения языка логического программирования Пролог и языка программирования Haskell для реализации алгоритма поиска оптимального каркаса графа. Алгоритм Прима, преимущество перед другими алгоритмами нахождения оптимального каркаса, близких к полным.

    курсовая работа [230,2 K], добавлен 13.06.2012

  • Особенности задач линейного программирования. Симплексный метод решения задач линейного программирования. Обоснование выбора языка, инструментария программирования, перечень идентификаторов и блок-схема алгоритма. Логическая схема работы программы.

    дипломная работа [2,4 M], добавлен 13.08.2011

  • Основные аналитические соотношения. Блок схемы и алгоритм решения задачи. Проверка работоспособности алгоритма вручную. Таблица идентификации переменных. Формы входной и выходной печати. Разработка и отладка программы. Инструкция для работы с программой.

    курсовая работа [69,8 K], добавлен 13.02.2012

  • Отделение действительных корней нелинейного уравнения. Метод хорд и касательных (Ньютона), геометрическая интерпретация. Графическая схема алгоритма. Описание реализации базовой модели в MathCAD. График сравнения числа итераций в зависимости от точности.

    курсовая работа [2,0 M], добавлен 16.05.2013

  • Особенности метода неопределенных множителей Лагранжа, градиентного метода и метода перебора и динамического программирования. Конструирование алгоритма решения задачи. Структурная схема алгоритма сценария диалога и описание его программной реализации.

    курсовая работа [1010,4 K], добавлен 10.08.2014

  • Структура, классификация и требования к реализации компилятора. Проектирование и реализация анализирующей части компилятора языка С++. Способы реализации лексического анализа. Алгоритм работы синтаксического анализатора. Принципы программной реализации.

    курсовая работа [774,2 K], добавлен 26.01.2013

  • История создания языка Java. Основные принципы объектно-ориентированного программирования. Структура, особенности синтаксиса и примеры прикладных возможностей использования языка Java, его преимущества. Перспективы работы программистом на языке Java.

    курсовая работа [795,9 K], добавлен 14.12.2012

  • Составление блок-схемы алгоритма решения задачи, погрешности вычисления суммы членов числового ряда. Разработка программ на языке на Visual Basic, работа с массивами. Особенности работы со строковыми данными. Варианты реализации формы приложения.

    контрольная работа [220,4 K], добавлен 18.06.2010

  • Программирование игр с использованием визуальных компонентов. Описание операторов, используемых при практической реализации разработанной программы. Работа над созданием программы "Морской бой", постановка задачи, алгоритм реализации работы, блок-схема.

    курсовая работа [175,9 K], добавлен 10.05.2010

  • Понятие алгоритма, его назначение, представление (изобразительные средства для описания), типы, способы записи, схемы. Основные принципы разработки алгоритмов и программ. Характеристика языков программирования. Средства и правила построения блок-схем.

    реферат [87,9 K], добавлен 26.03.2010

  • Понятие графика функции и его представление на ЭВМ. Алгоритм реализации, блок-схема и функциональные тесты графического метода решения частного случая задачи нелинейного программирования, его математическая модель. Диалог программы с пользователем.

    курсовая работа [1,6 M], добавлен 15.05.2012

  • Выбор языка программирования и его обоснование. Определение системных требований. Схема алгоритма и программа на языке Qbasic. Разработка руководства пользователя. Способы конструирования программ. Особенности и принципы динамического программирования.

    курсовая работа [398,8 K], добавлен 21.01.2014

  • Решение задачи по методу Адамса. Блок-схема функции main. Блок-схема функции Adams. Листинг программы. Блок-схема функции MMinor. Блок-схема функции MatrixMultiply. Блок-схема функции Determinant. Результат решения задачи на ЭВМ.

    курсовая работа [68,9 K], добавлен 16.04.2004

  • Решение трансцендентного уравнения методом Ньютона. Построение графика функции. Блок-схема алгоритма решения задачи и программа решения на языке Pascal. Вычисление значения интеграла методом трапеции, блок-схема алгоритма, погрешности вычисления.

    задача [163,4 K], добавлен 16.12.2009

  • Создание стека с помощью языка программирования C#. Блок-схема работы алгоритма программы, ее интерфейс. Добавление, удаление и вывод элементов в стеке. Реализация методов "Начало-конец" (переприсвоение индексов) и "Приоритет" (сортировка по возрастанию).

    лабораторная работа [924,7 K], добавлен 26.12.2014

  • Этапы подготовки и решения реальных задач. Словесно-формульное, графическое описание, псевдокоды. Программа нахождения квадрата числа на языке Бейсик. Разветвляющийся и циклический алгоритм. Общие положения программирования. Базовые конструкции.

    презентация [308,3 K], добавлен 31.10.2016

  • Ознакомление с возможностями языка Си как средой программирования высокого уровня. Циклы программирования параметрического оператора for и функции форматированного ввода. Разработка программы средствами Си: блок-схема, текст и тестирование программы.

    контрольная работа [204,4 K], добавлен 26.01.2013

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.