Лекция 2: Основные этапы решения задач на ЭВМ
Природа больше любит женщин, а мужчины - расходный материал.
Введение
Программирование - процесс создания и модификации программ.
Программы = алгоритмы + структуры данных
Цель программирования - описание процесса обработки информации.
Данные - формализованное представление фактов.
Информация — осмысленное представление данных.
Знания — обработанная информация, используемая для принятия решений.
Основные этапы решения задач на ЭВМ
- Постановка задачи: Определение целей и требований.
- Анализ и исследование: Изучение методов решения.
- Разработка математической модели: Формулировка задачи через уравнения.
- Проектирование алгоритма: Разработка последовательности действий.
- Программирование: Написание кода.
- Тестирование и отладка: Проверка и исправление ошибок.
- Эксплуатация и сопровождение: Внедрение и поддержка.
- Анализ результатов: Оценка точности результатов.
Классификация языков программирования
Языки программирования можно классифицировать по различным критериям:
По парадигме программирования
- Императивные языки: Основаны на последовательности команд, изменяющих состояние программы (например, C).
- Декларативные языки: Основаны на описании желаемого результата, а не на последовательности действий (например, SQL).
- Функциональные языки: Основаны на применении функций, избегая изменяемых состояний (например, Haskell).
- Объектно-ориентированные языки: Основаны на концепции объектов и классов (например, Java, C++).
- Логические языки: Основаны на формальной логике (например, Prolog).
По назначению
- Системные языки: Разработаны для системного программирования (например, C, Rust).
- Прикладные языки: Предназначены для решения конкретных задач (например, MATLAB, R).
- Сценарные языки: Разработаны для написания скриптов (например, Bash, Perl).
По степени типизации
- Строго типизированные языки: Требуют явного указания типов данных (например, Java).
- Слабо типизированные языки: Допускают неявные преобразования типов (например, JavaScript).
По времени компиляции
- Компилируемые языки: Код компилируется в машинный код до выполнения (например, C).
- Интерпретируемые языки: Код выполняется интерпретатором на лету (например, Python).
По кроссплатформенности
- Кроссплатформенные языки: Поддерживаются на нескольких операционных системах (например, Java, Python).
По уровню абстракции
- Низкоуровневые языки: Близки к машинному коду (например, ассемблер).
- Высокоуровневые языки: Обеспечивают высокий уровень абстракции, удобный для человека (например, Python, Java).
Алгоритм и его свойства
Алгоритм — это точное предписание, которое приводит от начальных данных к искомому результату. Алгоритм должен обладать следующими свойствами:
- Определенность: Алгоритм должен быть однозначным.
- Результативность: Алгоритм должен приводить к результату.
- Массовость: Алгоритм должен решать класс задач.
- Дискретность: Алгоритм состоит из конечного числа шагов.
Способы записи алгоритмов:
- Вербальный: Запись на естественном языке.
- Формульно-словесный: Использование формул и текста.
- Графический: Блок-схемы, диаграммы.
- Алгоритмический язык: Язык, специально разработанный для записи алгоритмов (например, псевдокод).
- UML-диаграммы: Используются для представления системы или процесса.
Типы вычислительных процессов:
- Линейный алгоритм: Последовательное выполнение действий.
- Ветвящийся алгоритм: Действия зависят от условий (например, нахождение корней квадратного уравнения).
- Циклический алгоритм: Повторение действий (например, вычисление значений функции для диапазона значений).
Примеры реализации алгоритмов на C
Пример линейного алгоритма на C
#include <stdio.h>
int main() {
double a = 5.0, b = 3.0, result;
result = a * b;
printf("Result: %.2lf\n", result);
return 0;
}
Пример разветвляющегося алгоритма на C (нахождение корней квадратного уравнения)
#include <stdio.h>
#include <math.h>
int main() {
double a, b, c, discriminant, root1, root2;
printf("Enter coefficients a, b, and c: ");
scanf("%lf %lf %lf", &a, &b, &c);
discriminant = b * b - 4 * a * c;
if (discriminant > 0) {
root1 = (-b + sqrt(discriminant)) / (2 * a);
root2 = (-b - sqrt(discriminant)) / (2 * a);
printf("Roots are: %.2lf and %.2lf\n", root1, root2);
} else if (discriminant == 0) {
root1 = -b / (2 * a);
printf("Root is: %.2lf\n", root1);
} else {
printf("No real roots.\n");
}
return 0;
}
Важный нюанс при компиляции с <math.h>
в Linux и FreeBSD
При компиляции программы на C, использующей <math.h>
, на Linux и FreeBSD необходимо указывать флаг -lm
, иначе возникнут ошибки линковки. Это связано с тем, что в этих ОС математическая библиотека (libm
) отделена от стандартной библиотеки C и требует явного подключения. На Windows это не требуется, так как libm
встроена в стандартную библиотеку.
gcc -Wall -g -o example.out 1.c **-lm**
Пример циклического алгоритма на C (вычисление значений функции)
#include <stdio.h>
int main() {
int x;
double b = 5.0, result;
for (x = -10; x <= 10; x += 2) {
result = x * x + b;
printf("f(%d) = %.2f\n", x, result);
}
return 0;
}