Alvaros
.
- Регистрация
- 14.05.16
- Сообщения
- 21.452
- Реакции
- 101
- Репутация
- 204
Решим классическую задачу Data Science на C99 и C++11.
В то время как такие языки как Python и R становятся все более популярными для науки о данных, C и C++ могут быть сильным выбором для эффективного решения задач в Data Science. В этой статье мы будем использовать C99 и C++11 для написания программы, работающей с квартетом Энскомба, о котором я расскажу далее.
О своей мотивации к постоянному изучению языков я написал в статье, посвященной Python и GNU Octave, которую стоит прочитать. Все программы предназначены для командной строки, а не для графического интерфейса пользователя (GUI). Полные примеры доступны в репозитории polyglot_fit.
Задача по программированию
Программа, которую вы напишете в этой серии:
Это обычная задача, с которой сталкиваются многие специалисты по данным. Примером данных является первый набор квартета Энскомба, представленный в таблице ниже. Это набор искусственно сконструированных данных, которые дают одинаковые результаты при подгонке под прямую, но их графики сильно отличаются. Файл данных — это текстовый файл с табами для разделения столбцов и несколькими строками, формирующими заголовок. В этой задаче будет использоваться только первый набор (т.е. первые две колонки).
Способ решения на С
C — язык программирования общего назначения, который является одним из наиболее популярных языков, используемых сегодня (по данным
Это язык, который я использую больше всего для
Я расскажу о необходимых предпосылках программирования на С и С++, чтобы и новички, и опытные пользователи могли воспользоваться этими языками.
Установка
Для разработки на C99 нужен компилятор. Обычно я использую
Установка в
sudo dnf install clang gnuplot gsl gsl-devel
Комментарии к коду
В C99
// Компилятор проигнорирует этот комментарий.
/* И этот тоже проигнорирует */
Необходимые библиотеки
Библиотеки состоят из двух частей:
Заголовочные файлы включаются в исходный код, а исходный код библиотек привязываются к исполняемому файлу. Следовательно, заголовочные файлы необходимы для данного примера:
// Инструменты ввода-вывода
#include
// Стандартная библиотека
#include
// Инструменты для работы с строками
#include
// Структура данных "очередь" от BSD
#include queue.h>
// Научные инструменты GSL
#include gsl_fit.h>
#include gsl_statistics_double.h>
Функция Main
В языке Си программа должна находиться внутри специальной функции, называемой
int main(void) {
...
}
Здесь можно заметить отличие от Python, о котором говорилось в последнем руководстве, потому что в случае с Python, будет выполняться любой код, который он найдет в исходных файлах.
Определение переменных
В C переменные должны быть объявлены до их использования, и они должны быть ассоциированы с типом. Всякий раз, когда вы хотите использовать переменную, вы должны решить, какие данные в ней хранить. Вы также можете указать, собираетесь ли вы использовать переменную в качестве константного значения, что не обязательно, но компилятор может извлечь выгоду из этой информации. Пример из программы
const char *input_file_name = "anscombe.csv";
const char *delimiter = "\t";
const unsigned int skip_header = 3;
const unsigned int column_x = 0;
const unsigned int column_y = 1;
const char *output_file_name = "fit_C99.csv";
const unsigned int N = 100;
Массивы в языке С не являются динамическими в том смысле, что их длина должна быть определена заранее (т.е. до компиляции):
int data_array[1024];
Так как вы обычно не знаете, сколько точек данных находится в файле, используйте
struct data_point {
double x;
double y;
SLIST_ENTRY(data_point) entries;
};
SLIST_HEAD(data_list, data_point) head = SLIST_HEAD_INITIALIZER(head);
SLIST_INIT(&head);
Этот пример определяет список data_point, состоящий из структурированных значений, которые содержат как значения x, так и значения y. Синтаксис довольно сложный, но интуитивно понятный, и его подробное описание было бы слишком многословным.
Вывод на печать
Для печати в терминале можно использовать функцию
printf("#### Первый набор квартета Энскомба на C99 ####\n");
Функция printf() не добавляет новую строку в конце распечатываемой строки автоматически, поэтому ее нужно добавлять собственноручно. Первый аргумент — это строка, которая может содержать информацию о формате других аргументов, которые могут быть переданы в функцию, например:
printf("Slope: %f\n", slope);
Чтение данных
Сейчас наступает сложная часть… Есть несколько библиотек для разбора CSV-файлов на C, но ни одна из них не оказалась достаточно стабильной или популярной, чтобы находиться в репозитории пакетов Fedora. Вместо того, чтобы добавлять зависимость для этого руководства, я решил написать эту часть самостоятельно. Опять же, вдаваться в подробности было бы слишком многословно, поэтому я буду объяснять только общую идею. Некоторые строки в исходном коде будут проигнорированы для краткости, но вы можете найти полный пример в репозитории.
Сначала откройте входной файл:
FILE* input_file = fopen(input_file_name, "r");
Затем читайте файл построчно до тех пор, пока не произойдет ошибка или пока файл не закончится:
while (!ferror(input_file) && !feof(input_file)) {
size_t buffer_size = 0;
char *buffer = NULL;
getline(&buffer, &buffer_size, input_file);
...
}
Функция
char *token = strtok(buffer, delimiter);
while (token != NULL)
{
double value;
sscanf(token, "%lf", &value);
if (column == column_x) {
x = value;
} else if (column == column_y) {
y = value;
}
column += 1;
token = strtok(NULL, delimiter);
}
Наконец, когда выбраны значения x и y, добавьте новую точку в список:
struct data_point *datum = malloc(sizeof(struct data_point));
datum->x = x;
datum->y = y;
SLIST_INSERT_HEAD(&head, datum, entries);
Функция
Подгонка данных
Функция линейной интерполяции из
const size_t entries_number = row - skip_header - 1;
double *x = malloc(sizeof(double) * entries_number);
double *y = malloc(sizeof(double) * entries_number);
Затем пройдите по списку, чтобы сохранить соответствующие данные в массивах:
SLIST_FOREACH(datum, &head, entries) {
const double current_x = datum->x;
const double current_y = datum->y;
x = current_x;
y = current_y;
i += 1;
}
Теперь, когда вы закончили со списком, наведите порядок. Всегда освобождайте память, которая была выделена вручную, чтобы
while (!SLIST_EMPTY(&head)) {
struct data_point *datum = SLIST_FIRST(&head);
SLIST_REMOVE_HEAD(&head, entries);
free(datum);
}
Наконец, наконец-то(!), вы можете подогнать свои данные:
gsl_fit_linear(x, 1, y, 1, entries_number,
&intercept, &slope,
&cov00, &cov01, &cov11, &chi_squared);
const double r_value = gsl_stats_correlation(x, 1, y, 1, entries_number);
printf("Slope: %f\n", slope);
printf("Intercept: %f\n", intercept);
printf("Correlation coefficient: %f\n", r_value);
Построение графика
Для построения графика необходимо использовать внешнюю программу. Поэтому сохраните функцию подгонки во внешнем файле:
const double step_x = ((max_x + 1) - (min_x - 1)) / N;
for (unsigned int i = 0; i < N; i += 1) {
const double current_x = (min_x - 1) + step_x * i;
const double current_y = intercept + slope * current_x;
fprintf(output_file, "%f\t%f\n", current_x, current_y);
}
Команда Gnuplot для построения графиков выглядит следующим образом:
plot 'fit_C99.csv' using 1:2 with lines title 'Fit', 'anscombe.csv' using 1:2 with points pointtype 7 title 'Data'
Результаты
Перед запуском программы необходимо ее скомпилировать:
clang -std=c99 -I/usr/include/ fitting_C99.c -L/usr/lib/ -L/usr/lib64/ -lgsl -lgslcblas -o fitting_C99
Эта команда говорит компилятору использовать стандарт C99, прочитать файл fitting_C99.c, загрузить библиотеки gsl и gslcblas и сохранить результат в fitting_C99. Полученный результат в командной строке:
#### Первый набор квартета Энскомба на C99 ####
Угловой коэффициент: 0.500091
Пересечение: 3.000091
Коэффициент корреляции: 0.816421
Вот результирующее изображение, сгенерированное с помощью Gnuplot.
Способ решения на С++11
Так как C++ в значительной степени совместим с C, я просто остановлюсь на различиях между ними. Если я не опишу какой-то раздел в этой части, это означает, что он такой же, как и в C.
Установка
Зависимости для C++ такие же, как и для примера C. На Fedora необходимо выполнить следующую команду:
sudo dnf install clang gnuplot gsl gsl-devel
Необходимые библиотеки
Библиотеки работают так же, как и на C, но директивы include немного отличаются:
#include
#include
#include
#include
#include
#include
#include
extern "C" {
#include gsl_fit.h>
#include gsl_statistics_double.h>
}
Поскольку библиотеки GSL написаны на С, компилятору необходимо сообщить об этой особенности.
Определение переменных
C++ поддерживает больше типов (классов) данных, чем C, например, строковый тип, который имеет гораздо больше возможностей, чем его C-аналог. Обновите определение переменных соответствующим образом:
const std::string input_file_name("anscombe.csv");
Для структурированных объектов, таких как строки, можно определить переменную без использования знака =.
Вывод на печать
Вы можете использовать функцию printf(), но более принято использовать cout. Используйте оператор b> для указания строки (или объектов), которые вы хотите распечатать с помощью cout:
std::cout code>
…
std::cout std::cout std::cout
Чтение данных
Схема такая же, как и раньше. Файл открывается и читается построчно, но с другим синтаксисом:
std::ifstream input_file(input_file_name);
while (input_file.good()) {
std::string line;
getline(input_file, line);
...
}
Токены строк извлекаются той же функцией, что и в примере C99. Вместо стандартных массивов из C используйте два
std::vector x;
std::vector y;
// Добавляем элементы в x и y
x.emplace_back(value);
y.emplace_back(value);
Подгонка данных
Для подгонки данных на С++ не нужно мучиться со списками, так как векторы гарантированно имеют последовательную память. Вы можете напрямую передать функции подгонки указатели на буферы векторов:
gsl_fit_linear(x.data(), 1, y.data(), 1, entries_number,
&intercept, &slope,
&cov00, &cov01, &cov11, &chi_squared);
const double r_value = gsl_stats_correlation(x.data(), 1, y.data(), 1, entries_number);
std::cout code>
Построение графика
Построение графика делается так же, как и раньше. Запишите в файл:
const double step_x = ((max_x + 1) - (min_x - 1)) / N;
for (unsigned int i = 0; i < N; i += 1) {
const double current_x = (min_x - 1) + step_x * i;
const double current_y = intercept + slope * current_x;
output_file code>
А потом используйте Gnuplot для построения графика.
Результаты
Перед запуском программы она должна быть скомпилирована аналогичной командой:
clang++ -std=c++11 -I/usr/include/ fitting_Cpp11.cpp -L/usr/lib/ -L/usr/lib64/ -lgsl -lgslcblas -o fitting_Cpp11
Результирующий вывод в командной строке:
#### Первый набор квартета Энскомба на C++11 ####
Угловой Коэффициент: 0.500091
Пересечение: 3.00009
Коэффициент корреляции: 0.816421
И вот полученное изображение, сгенерированное с помощью Gnuplot.
Заключение
В статье приведены примеры подгонки данных и построения графиков на C99 и C++11. Так как C++ в значительной степени совместим с C, в данной статье использовано их сходство для написания второго примера. В некоторых аспектах Си++ проще использовать, так как он частично снимает нагрузку по явному управлению памятью, но его синтаксис сложнее, так как он вводит возможность написания классов для ООП. Тем не менее, вы можете писать и на C с использованием методов ООП, так как ООП — это стиль программирования, его можно использовать на любом языке. Есть несколько замечательных примеров ООП на Си, таких как библиотеки
Для работы с числами я предпочитаю использовать C99 из-за его более простого синтаксиса и широкой поддержки. До недавнего времени С++11 не так широко поддерживался, и я старался избегать шероховатостей в предыдущих версиях. Для более сложного программного обеспечения, C++ может быть хорошим выбором.
Вы используете С или С++ для Data Science? Поделитесь своим опытом в комментариях.
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
Читать еще
В то время как такие языки как Python и R становятся все более популярными для науки о данных, C и C++ могут быть сильным выбором для эффективного решения задач в Data Science. В этой статье мы будем использовать C99 и C++11 для написания программы, работающей с квартетом Энскомба, о котором я расскажу далее.
О своей мотивации к постоянному изучению языков я написал в статье, посвященной Python и GNU Octave, которую стоит прочитать. Все программы предназначены для командной строки, а не для графического интерфейса пользователя (GUI). Полные примеры доступны в репозитории polyglot_fit.
Задача по программированию
Программа, которую вы напишете в этой серии:
- Считывает данные из
You must be registered for see links
- Интерполирует данные прямой линией (т.е., f(x)=m ⋅ x + q).
- Записывает результат в файл изображения
Это обычная задача, с которой сталкиваются многие специалисты по данным. Примером данных является первый набор квартета Энскомба, представленный в таблице ниже. Это набор искусственно сконструированных данных, которые дают одинаковые результаты при подгонке под прямую, но их графики сильно отличаются. Файл данных — это текстовый файл с табами для разделения столбцов и несколькими строками, формирующими заголовок. В этой задаче будет использоваться только первый набор (т.е. первые две колонки).
You must be registered for see links
Способ решения на С
C — язык программирования общего назначения, который является одним из наиболее популярных языков, используемых сегодня (по данным
You must be registered for see links
,
You must be registered for see links
,
You must be registered for see links
, и
You must be registered for see links
). Это достаточно старый язык (он был создан примерно в 1973 году), и на нем было написано много успешных программ (например, ядро Linux и Git). Этот язык также максимально приближен к внутренней работе компьютера, так как используется для непосредственного управления памятью. Это
You must be registered for see links
, поэтому исходный код должен быть транслирован
You must be registered for see links
в
You must be registered for see links
. Его
You must be registered for see links
небольшая и легкая по размерам, поэтому были разработаны другие библиотеки, обеспечивающие недостающие функциональные возможности.Это язык, который я использую больше всего для
You must be registered for see links
, в основном из-за его производительности. Я нахожу его довольно утомительным в использовании, так как он требует написания большого
You must be registered for see links
, но он хорошо поддерживается в различных средах. Стандарт C99 — это недавняя ревизия, которая добавляет некоторые изящные возможности и хорошо поддерживается компиляторами.Я расскажу о необходимых предпосылках программирования на С и С++, чтобы и новички, и опытные пользователи могли воспользоваться этими языками.
Установка
Для разработки на C99 нужен компилятор. Обычно я использую
You must be registered for see links
, но подойдет и
You must be registered for see links
– еще один полноценный компилятор с открытым исходным кодом. Для подгонки данных я решил использовать
You must be registered for see links
. Для построения графиков я не смог найти никакой разумной библиотеки, и поэтому эта программа полагается на внешнюю программу:
You must be registered for see links
. В примере также используется динамическая структура данных для хранения данных, которая определена в Дистрибутиве программ Беркли (
You must be registered for see links
).Установка в
You must be registered for see links
очень проста:sudo dnf install clang gnuplot gsl gsl-devel
Комментарии к коду
В C99
You must be registered for see links
форматируются путем добавления // в начало строки, а остальная часть строки будет отброшена интерпретатором. Все, что находится между /* и */, также отбрасывается.// Компилятор проигнорирует этот комментарий.
/* И этот тоже проигнорирует */
Необходимые библиотеки
Библиотеки состоят из двух частей:
-
You must be registered for see links, содержащий описание функций
- Исходный файл, содержащий определения функций
Заголовочные файлы включаются в исходный код, а исходный код библиотек привязываются к исполняемому файлу. Следовательно, заголовочные файлы необходимы для данного примера:
// Инструменты ввода-вывода
#include
// Стандартная библиотека
#include
// Инструменты для работы с строками
#include
// Структура данных "очередь" от BSD
#include queue.h>
// Научные инструменты GSL
#include gsl_fit.h>
#include gsl_statistics_double.h>
Функция Main
В языке Си программа должна находиться внутри специальной функции, называемой
You must be registered for see links
:int main(void) {
...
}
Здесь можно заметить отличие от Python, о котором говорилось в последнем руководстве, потому что в случае с Python, будет выполняться любой код, который он найдет в исходных файлах.
Определение переменных
В C переменные должны быть объявлены до их использования, и они должны быть ассоциированы с типом. Всякий раз, когда вы хотите использовать переменную, вы должны решить, какие данные в ней хранить. Вы также можете указать, собираетесь ли вы использовать переменную в качестве константного значения, что не обязательно, но компилятор может извлечь выгоду из этой информации. Пример из программы
You must be registered for see links
, находящейся в репозитории:const char *input_file_name = "anscombe.csv";
const char *delimiter = "\t";
const unsigned int skip_header = 3;
const unsigned int column_x = 0;
const unsigned int column_y = 1;
const char *output_file_name = "fit_C99.csv";
const unsigned int N = 100;
Массивы в языке С не являются динамическими в том смысле, что их длина должна быть определена заранее (т.е. до компиляции):
int data_array[1024];
Так как вы обычно не знаете, сколько точек данных находится в файле, используйте
You must be registered for see links
. Это динамическая структура данных, которая может расти бесконечно. К счастью, BSD
You must be registered for see links
. Вот пример определения:struct data_point {
double x;
double y;
SLIST_ENTRY(data_point) entries;
};
SLIST_HEAD(data_list, data_point) head = SLIST_HEAD_INITIALIZER(head);
SLIST_INIT(&head);
Этот пример определяет список data_point, состоящий из структурированных значений, которые содержат как значения x, так и значения y. Синтаксис довольно сложный, но интуитивно понятный, и его подробное описание было бы слишком многословным.
Вывод на печать
Для печати в терминале можно использовать функцию
You must be registered for see links
, которая работает как функция printf() в Octave (описанная в первой статье):printf("#### Первый набор квартета Энскомба на C99 ####\n");
Функция printf() не добавляет новую строку в конце распечатываемой строки автоматически, поэтому ее нужно добавлять собственноручно. Первый аргумент — это строка, которая может содержать информацию о формате других аргументов, которые могут быть переданы в функцию, например:
printf("Slope: %f\n", slope);
Чтение данных
Сейчас наступает сложная часть… Есть несколько библиотек для разбора CSV-файлов на C, но ни одна из них не оказалась достаточно стабильной или популярной, чтобы находиться в репозитории пакетов Fedora. Вместо того, чтобы добавлять зависимость для этого руководства, я решил написать эту часть самостоятельно. Опять же, вдаваться в подробности было бы слишком многословно, поэтому я буду объяснять только общую идею. Некоторые строки в исходном коде будут проигнорированы для краткости, но вы можете найти полный пример в репозитории.
Сначала откройте входной файл:
FILE* input_file = fopen(input_file_name, "r");
Затем читайте файл построчно до тех пор, пока не произойдет ошибка или пока файл не закончится:
while (!ferror(input_file) && !feof(input_file)) {
size_t buffer_size = 0;
char *buffer = NULL;
getline(&buffer, &buffer_size, input_file);
...
}
Функция
You must be registered for see links
является приятным недавним дополнением из
You must be registered for see links
. Она может читать целую строку в файле и заботиться о выделении необходимой памяти. Каждая строка затем разбивается на
You must be registered for see links
с помощью функции
You must be registered for see links
. Просматривая токен, выберите нужные вам столбцы:char *token = strtok(buffer, delimiter);
while (token != NULL)
{
double value;
sscanf(token, "%lf", &value);
if (column == column_x) {
x = value;
} else if (column == column_y) {
y = value;
}
column += 1;
token = strtok(NULL, delimiter);
}
Наконец, когда выбраны значения x и y, добавьте новую точку в список:
struct data_point *datum = malloc(sizeof(struct data_point));
datum->x = x;
datum->y = y;
SLIST_INSERT_HEAD(&head, datum, entries);
Функция
You must be registered for see links
динамически выделяет (резервирует) некоторый объем постоянной памяти для новой точки.Подгонка данных
Функция линейной интерполяции из
You must be registered for see links
принимает на вход обычные массивы. Поэтому, так как вы не можете заранее знать размер создаваемых массивов, необходимо вручную выделить на них память:const size_t entries_number = row - skip_header - 1;
double *x = malloc(sizeof(double) * entries_number);
double *y = malloc(sizeof(double) * entries_number);
Затем пройдите по списку, чтобы сохранить соответствующие данные в массивах:
SLIST_FOREACH(datum, &head, entries) {
const double current_x = datum->x;
const double current_y = datum->y;
x = current_x;
y = current_y;
i += 1;
}
Теперь, когда вы закончили со списком, наведите порядок. Всегда освобождайте память, которая была выделена вручную, чтобы
You must be registered for see links
. Утечка памяти — это плохо, плохо, и еще раз плохо. Каждый раз, когда память не освобождается, садовый гном лишается головы:while (!SLIST_EMPTY(&head)) {
struct data_point *datum = SLIST_FIRST(&head);
SLIST_REMOVE_HEAD(&head, entries);
free(datum);
}
Наконец, наконец-то(!), вы можете подогнать свои данные:
gsl_fit_linear(x, 1, y, 1, entries_number,
&intercept, &slope,
&cov00, &cov01, &cov11, &chi_squared);
const double r_value = gsl_stats_correlation(x, 1, y, 1, entries_number);
printf("Slope: %f\n", slope);
printf("Intercept: %f\n", intercept);
printf("Correlation coefficient: %f\n", r_value);
Построение графика
Для построения графика необходимо использовать внешнюю программу. Поэтому сохраните функцию подгонки во внешнем файле:
const double step_x = ((max_x + 1) - (min_x - 1)) / N;
for (unsigned int i = 0; i < N; i += 1) {
const double current_x = (min_x - 1) + step_x * i;
const double current_y = intercept + slope * current_x;
fprintf(output_file, "%f\t%f\n", current_x, current_y);
}
Команда Gnuplot для построения графиков выглядит следующим образом:
plot 'fit_C99.csv' using 1:2 with lines title 'Fit', 'anscombe.csv' using 1:2 with points pointtype 7 title 'Data'
Результаты
Перед запуском программы необходимо ее скомпилировать:
clang -std=c99 -I/usr/include/ fitting_C99.c -L/usr/lib/ -L/usr/lib64/ -lgsl -lgslcblas -o fitting_C99
Эта команда говорит компилятору использовать стандарт C99, прочитать файл fitting_C99.c, загрузить библиотеки gsl и gslcblas и сохранить результат в fitting_C99. Полученный результат в командной строке:
#### Первый набор квартета Энскомба на C99 ####
Угловой коэффициент: 0.500091
Пересечение: 3.000091
Коэффициент корреляции: 0.816421
Вот результирующее изображение, сгенерированное с помощью Gnuplot.
Способ решения на С++11
You must be registered for see links
— язык программирования общего назначения, который также является одним из самых популярных языков, используемых сегодня. Он был создан как
You must be registered for see links
языка С (в 1983 году) с акцентом на
You must be registered for see links
(ООП). С++ обычно считается надмножеством С, поэтому программа на С должна быть скомпилирована компилятором Си++. Это получается не всегда, так как есть некоторые краевые случаи, когда они ведут себя по-разному. По моему опыту, С++ требует меньше шаблонного кода, чем С, но его синтаксис сложнее, если вы хотите разрабатывать объекты. Стандарт C++11 — это недавняя ревизия, которая добавляет некоторые изящные возможности, которые более или менее поддерживается компиляторами.Так как C++ в значительной степени совместим с C, я просто остановлюсь на различиях между ними. Если я не опишу какой-то раздел в этой части, это означает, что он такой же, как и в C.
Установка
Зависимости для C++ такие же, как и для примера C. На Fedora необходимо выполнить следующую команду:
sudo dnf install clang gnuplot gsl gsl-devel
Необходимые библиотеки
Библиотеки работают так же, как и на C, но директивы include немного отличаются:
#include
#include
#include
#include
#include
#include
#include
extern "C" {
#include gsl_fit.h>
#include gsl_statistics_double.h>
}
Поскольку библиотеки GSL написаны на С, компилятору необходимо сообщить об этой особенности.
Определение переменных
C++ поддерживает больше типов (классов) данных, чем C, например, строковый тип, который имеет гораздо больше возможностей, чем его C-аналог. Обновите определение переменных соответствующим образом:
const std::string input_file_name("anscombe.csv");
Для структурированных объектов, таких как строки, можно определить переменную без использования знака =.
Вывод на печать
Вы можете использовать функцию printf(), но более принято использовать cout. Используйте оператор b> для указания строки (или объектов), которые вы хотите распечатать с помощью cout:
std::cout code>
…
std::cout std::cout std::cout
Чтение данных
Схема такая же, как и раньше. Файл открывается и читается построчно, но с другим синтаксисом:
std::ifstream input_file(input_file_name);
while (input_file.good()) {
std::string line;
getline(input_file, line);
...
}
Токены строк извлекаются той же функцией, что и в примере C99. Вместо стандартных массивов из C используйте два
You must be registered for see links
. Векторы являются расширением массивов C в
You must be registered for see links
C++, позволяющим динамически управлять памятью без вызова malloc():std::vector x;
std::vector y;
// Добавляем элементы в x и y
x.emplace_back(value);
y.emplace_back(value);
Подгонка данных
Для подгонки данных на С++ не нужно мучиться со списками, так как векторы гарантированно имеют последовательную память. Вы можете напрямую передать функции подгонки указатели на буферы векторов:
gsl_fit_linear(x.data(), 1, y.data(), 1, entries_number,
&intercept, &slope,
&cov00, &cov01, &cov11, &chi_squared);
const double r_value = gsl_stats_correlation(x.data(), 1, y.data(), 1, entries_number);
std::cout code>
Построение графика
Построение графика делается так же, как и раньше. Запишите в файл:
const double step_x = ((max_x + 1) - (min_x - 1)) / N;
for (unsigned int i = 0; i < N; i += 1) {
const double current_x = (min_x - 1) + step_x * i;
const double current_y = intercept + slope * current_x;
output_file code>
А потом используйте Gnuplot для построения графика.
Результаты
Перед запуском программы она должна быть скомпилирована аналогичной командой:
clang++ -std=c++11 -I/usr/include/ fitting_Cpp11.cpp -L/usr/lib/ -L/usr/lib64/ -lgsl -lgslcblas -o fitting_Cpp11
Результирующий вывод в командной строке:
#### Первый набор квартета Энскомба на C++11 ####
Угловой Коэффициент: 0.500091
Пересечение: 3.00009
Коэффициент корреляции: 0.816421
И вот полученное изображение, сгенерированное с помощью Gnuplot.
Заключение
В статье приведены примеры подгонки данных и построения графиков на C99 и C++11. Так как C++ в значительной степени совместим с C, в данной статье использовано их сходство для написания второго примера. В некоторых аспектах Си++ проще использовать, так как он частично снимает нагрузку по явному управлению памятью, но его синтаксис сложнее, так как он вводит возможность написания классов для ООП. Тем не менее, вы можете писать и на C с использованием методов ООП, так как ООП — это стиль программирования, его можно использовать на любом языке. Есть несколько замечательных примеров ООП на Си, таких как библиотеки
You must be registered for see links
и
You must be registered for see links
.Для работы с числами я предпочитаю использовать C99 из-за его более простого синтаксиса и широкой поддержки. До недавнего времени С++11 не так широко поддерживался, и я старался избегать шероховатостей в предыдущих версиях. Для более сложного программного обеспечения, C++ может быть хорошим выбором.
Вы используете С или С++ для Data Science? Поделитесь своим опытом в комментариях.
Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя платные онлайн-курсы SkillFactory:
-
You must be registered for see links(12 недель)
-
You must be registered for see links(12 месяцев)
-
You must be registered for see links(9 месяцев)
-
You must be registered for see links(9 месяцев)
Читать еще
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links



