Московский государственный индустриальный университет
Опубликован: 27.09.2006 | Доступ: свободный | Студентов: 3332 / 380 | Оценка: 4.17 / 3.79 | Длительность: 24:17:00
Специальности: Программист
Лекция 1:

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

Лекция 1: 12 || Лекция 2 >

Парадигмы программирования

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

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

C и Pascal являются примерами языков, предназначенных для директивного программирования (directive programming), когда разработчик программы использует процессно-ориентированную модель, то есть пытается создать код, должным образом воздействующий на данные. Активным началом при этом подходе считается программа (код), которая должна выполнить все необходимые для достижения нужного результата действия над пассивными данными.

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

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

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

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

Текст программы

public class MinDivider {
    public static void main(String[] args) throws Exception {    
        int k = Xterm.inputInt("Введите натуральное число," +
                               "большее единицы: ");
        int i = 2;
        while (k%i != 0)
            i++;
        Xterm.println("Наименьший простой делитель числа " +
                    k + " равен " + i);
    }
}

Функциональное и логическое программирование использует языки типа Lisp, Haskell и Prolog. Эта парадигма базируется на принципиально иной трактовке понятия программы. Здесь главным является точная формулировка задачи, а выбор и применение необходимого алгоритма для ее решения — проблема исполняющей системы, но не программиста.

Задачи для самостоятельного решения

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

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

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

Задача 1.6.Придумайте алгоритм, вводящий действительное число, который рассматривает это число, как координаты точки на прямой, и находит расстояние от этой точки до отрезка [0,1].

Задача 1.7.Придумайте алгоритм, находящий n -ое простое число.

Функциональное программирование

Для того чтобы представить себе стиль, в котором пишутся программы при использовании функциональных языков, рассмотрим несколько примеров программ на языке Haskell. Сначала разберем две программы, вычисляющие факториал n! натурального числа n в соответствии с его различными определениями.

Первое определение n! имеет вид n! = 1 \cdot 2 \cdot \ldots \cdot n, а соответствующая ему программа не содержит ничего, кроме записи этого определения на языке Haskell:

f n = product [1..n]

Второе определение факториала расширяет область определения этой операции и является рекурсивным.

0! &= 1,\\
n! &= n \cdot (n-1)! \quad\text{для}\quad n > 0.

Программа, написанная в соответствии с ним, тоже является просто его переформулировкой:

f 0 = 1

f x = x * f (x-1)

В качестве значительно более сложного примера приведем текст программы, которая находит и печатает все варианты таких расстановок символов +, -,*,/ и круглых скобок в n -значном номере билета, что результатом вычислений будет число 100. Операция деления при этом допустима только в случае деления нацело, а количество n цифр в билете может быть произвольным. Программа решения этой задачи на языке Haskell является удивительно короткой:

Текст программы

tickets ds = (ds, foldl (\n c -> 10*n + digitToInt c) 0 ds) :
 [("("++ld++[op]++rd++")", f lv rv) |
    (op,f) <- [('+',(+)),('-',(-)),('*',(*)),('/',(div))],
      n<-[1..length ds-1], (ld,lv) <- tickets (take n ds),
        (rd,rv) <- tickets (drop n ds), op /= '/' || (rv /= 0
          && lv `mod` rv == 0)]
happy = map fst . (filter ((==)100 . snd)) . tickets

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

Для запуска этой программы на компьютере, где установлен интерпретатор hugs языка Haskell, достаточно запустить его (набрав hugs ), а затем выполнить команды загрузки файла с программой ( :load ticket ) и запуска ее на выполнение. Последняя команда должна содержать в качестве параметра последовательность цифр билета в кавычках. Вот пример задания и полученного результата:

Main> (happy "234112")
["((2*(3+41))+12)","((2+3)*((41-1)/2))","(((2*3)+(4*11))*2)",
"(((2+3)*(41-1))/2)"]
Elapsed time (ms): 33150 (user), 20 (system)
Main>

Для выхода из интерпретатора hugs используйте команду :quit, а мы далее в этой книге не будем больше касаться проблем, связанных с функциональным или логическим программированием, — этому будут посвящены отдельные дисциплины на старших курсах обучения.

Лекция 1: 12 || Лекция 2 >
Анастасия Халудорова
Анастасия Халудорова
екатерина яковлева
екатерина яковлева