
- •Матеріали для підготовки до держіспиту
- •Програмування
- •1. Об’єкти. Поняття об’єкту у процедурному та об’єктно-орієнтованому програмуванні
- •2. Загальні принципи і основні елементи об’єктно-орієнтованого програмування
- •3. Типи та класи у сучасній мові програмування. Взаємовідношення понять "клас" та "об’єкт"
- •4. Поліморфізм як одна з компонентів ідеології сучасного програмування
- •5. Принцип модульності у програмуванні. Процедури і функції, їх побудова та застосування
- •6. Динамічний розподіл ресурсів пам’яті при виконанні програми
- •7. Застосування шаблонів функцій та класів при створенні програм. Можливості параметризованих класів.
- •8. Успадкування та створення ієрархій класів. Проблеми, які вирішуються шляхом використання успадкування
- •9. Атрибути доступу як засіб підвищення надійності програмування
- •Теорія систем та математичне моделювання
- •10. Основні поняття теорії систем. Класифікація систем
- •11. Методи опису систем
- •12. Математичні та комп’ютерні моделі. Їх види та характеристики
- •13. Ідентифікація моделей і задача апроксимації. Методи апроксимації даних
- •14. Моделювання стаціонарних систем. Нелінійні системи
- •15. Моделювання динаміки систем. Системи з локалізованими та розподіленими властивостями.
- •Аналіз та побудова алгоритмів
- •16. Поняття алгоритму. Види алгоритмів, способи їх подання.
- •17. Оцінювання ефективності алгоритму. Функція складності.
- •18. Математичний аналіз і емпіричне дослідження алгоритмів.
- •19. Обчислювальна складність задач. Класи задач p та np.
- •20. Функція складності алгоритму та асимптотичні відношення.
18. Математичний аналіз і емпіричне дослідження алгоритмів.
Эффективность работы алгоритма можно установить, используя теоретический либо экспериментальный методы его исследования. Теоретический метод предполагает использование специальных методов математического анализа алгоритмов, целью которого является установление свойств функции сложности изучаемого алгоритма. При использовании экспериментального метода свойства функции сложности изучаются путем проведения соответствующих расчетов, которые выполняются с использованием специальных методик.
У каждого из указанных двух подходов есть свои плюсы и минусы. Математический анализ позволяет получить результаты, которые носят общий, фундаментальный и строгий характер. В то же время сам процесс математического анализа заданного алгоритма может быть весьма сложным, он требует непростой техники построения математических доказательств и зачастую на этом путь просто не удается получить требуемый результат. Последнее сужает круг алгоритмов, которые могут быть изучены таким путем.
Экспериментальный подход применим к намного более широкому кругу алгоритмов, однако получаемые результаты не имеют такого уровня общности и строгости, как в случае математического анализа. В качестве предварительного исследования алгоритма экспериментальный подход вполне уместен и полезен.
Измерение временных промежутков
Использование стандартных средств.
Использование средств модуля syst.h. Функции runtimer и timer.
Использование функций микросекундного таймера runstimer и mcstimer. Об идее использования регистра процессора TSC для построения таймера можно прочитать в книге [ Кулаков В. Программирование на аппаратном уровне. Специальный справочник.- СПб.: Питер, 2001.- 496 с.]
Ниже приводится пример построения программы Program_B, которая предназначена для численного исследования эффективности алгоритма сортировки методом пузырька. Программа позволяет получить таблицу, представляющую функцию сложности алгоритма сортировки, которая записывается в файл B.out.
Приведенные программы можно использовать как образец для исследования эффективности других алгоритмов.
// Program_B
#define _STIMER_
#include <syst.h>
void sort(int* A, int n)
{ алгоритм сортировки заданным методом
}
const int M=10; // M – число точек на графике
void main()
{ randomize(); // не обязательно
set_cpu_fr(); // установка такт. частоты действующего процессора
printf("CPU_Fr = %6.1f \n",CPU_Frequency); // не обязательно
int i,k, n=32; // величину n необходимо подобрать
unsigned long t; // переменная t должна иметь целый тип
double x[M],y[M];
int* a;
FILE* out= fopen("B.out","w");
fprintf(out,"%4d \n",M);
for (k=0;k<M;k++)
{ a= new int[n];
for (i=0;i<n;i++) a[i]= random(1000000);
runstimer();
sort(a,n);
t=mcstimer();
x[k]=log2(n); y[k]=log2(t);
printf("k=%2d n=%6d t=%7lu log2(n)=%6.3f log2(t)=%6.3f \n", k,n,t,x[k],y[k]);
fprintf(out,"%6.3f %6.3f \n",x[k],y[k]);
n*=sqrt(2); // можно использовать другой множитель
delete[] a;
}
double a0,a1;
linappr(M,x,y,a0,a1); // лин. аппроксимация средствами syst.h
printf("P = %6.4f \n",a1); // P – порядок алгоритма
delete[] a;
fclose(out);
puts("------- Program was finished ------");
pause;
}
Получение случайных чисел, векторов и матриц
Для тестирования алгоритмов линейной алгебры часто используются наборы (векторы, матрицы) случайных чисел. Стандартная библиотека C содержит функцию random(Max) , которая позволяет получать случайные целые числа из интервала [0,Max-1]. Для получения случайного числа вещественного типа можно использовать функцию frand(a,b) из модуля syst.h, которая генерирует случайные числа из заданного интервала [a,b]. Тип возвращаемого значения - double. Ниже приведен фрагмент программы, который формирует случайный вектор V и случайную матрицу M.
#include <syst.h>
const int N=20;
void main()
{ double V[N], M[N][N];
int i,k;
double a,b;
randomize();
a=-10; b=10;
for (i=0;i<N;i++) V[i]=frand(a,b);
for (i=0;i<N;i++) for (k=0;k<N;k++) M[i,k]=frand(a,b);
....................................................
}