Комментарии 10
Интерполирует данные прямой линией (т.е., f(x)=m ⋅ x + q).
Функция линейной интерполяции из GSL gsl_fit_linear() принимает на вход обычные массивы.
Это не интерполяция, это скорее аппроксимация, ну или фитирование (fitting).
Все же мне абсолютно не понятно, зачем использовать C/C++ для такого.
В языках, специально для этого созданных, манипуляции такого уровня занимают примерно 2 строчки. 4 если добавить считывание данных из .csv
и сохранение графика в файл.
plot(mtcars$disp, mtcars$hp)
lines(mtcars$disp, lm(hp ~ disp, mtcars)$fitted.values)
Created on 2020-07-06 by the reprex package (v0.3.0)
Почему бы не использовать готовые библиотеки для чтения CSV? На практике при его парсинге встречаются разные особенности, которые запаришься отлавливать.
1) «Массивы в языке С не являются динамическими» — в C99 как раз динамические массивы есть (в статье сказано «мы будем использовать C99» — а не просто «C»)
2) «использовать C99 из-за… широкой поддержки» — на самом деле, как раз наоборот. В частности, Microsoft Visual Studio до сих пор не поддерживает C99 полностью (в отличии от C++11)
Ну и, до кучи, CSV означает comma-separated values, парсить их используя delimiter="\t"… как-то странно. (про осмысленность использования C/C++ для написания довольно кривой обертки для пакета GSL уже написали)
про осмысленность использования C/C++ для написания довольно кривой обертки для пакета GSL уже написали
Ну, все-таки в скорострельности с/с++ не откажешь, и те же операции по парсингу наборов данных (иногда весьма веселых) на этих языках могут серьезно сокращать время обработки. Особенно, если изменения нужно в онлайне смотреть…
Я совершенно упустил еще одну проблему у данного подхода:
Так как вы обычно не знаете, сколько точек данных находится в файле, используйте односвязный список. Это динамическая структура данных, которая может расти бесконечно. К счастью, BSD предоставляет односвязные списки. Вот пример определения:|
Этот пример определяет список data_point, состоящий из структурированных значений, которые содержат как значения x, так и значения y. Синтаксис довольно сложный, но интуитивно понятный, и его подробное описание было бы слишком многословным.
Связный список, конечно, удобен для хранения данных, которые вы получаете построчно (например, из человеко-читаемого файла типа .csv
). Однако, такой способ хранения довольно неэффективен. Во-первых, обычно количество записей в таблице не меняется в результате операций (ну или уменьшается до 1-3 если считается какой-то статистический параметр по столбцу, типа среднего). Количество столбцов же, наоборот, переменно.
Представьте ситуацию, что из [x; y]
нужно получить новое значение, "расстояние до точки [x0; y0]
". В таблице должен появиться новый столбец, R = sqrt((x - x0) ^ 2 + (y - y0) ^ 2)
, чего не сделать если тип вашей табличной строки прибит гвоздями в compile-time и не поддерживает легко изменения.
Альтренативно можно хранить данные по столбцам. Тогда каждый столбец — контейнер примитивного (ну или довольно простого, типа строки) типа. Все столбцы имеют одинаковую длину, количество столбцов можно менять — легко удалять, перемещать, добавлять новые, манипулируя просто указателями, не меняя положения даных в памяти пока это не потребуется.
Достаточно создать тип-заголовок для каждого столбца, содержащий, например, имя столбца, тип хранимых данных и условный void*
на участок памяти, а таблица будет содержать информацию о свом размере (строки и столбцы), и указатель типа PColDef*
со столбцами. Даже C99
должен такое осилить.
Теперь вашими данными легко манипулировать, а код — легко адаптировать если тип (а точнее форма) входных данных изменится.
К счастью, BSD предоставляет односвязные списки.Точно «саентист» переводил (или писал оригинал) :)
Память может закончиться гораздо раньше, чем будет достигнут конец чтения файлов, из-за дикого выделения мелких объектов и дефрагментации. К примеру, на моем ПК (16Гб ОЗУ) загнать телефонные CDR в память таким образом получается не более 5 000 000 строк (правда это QT-фреймворк и контейнер — QMap, структура CDR поболее 2-х столбцов). Далее, машина перестает ворочаться…
В принципе, редко бывает необходимость в таком объеме, в противном случае пришлось бы городить огород с предварительным запросом кол-ва записей, выделением массива под это дело.
Использование C и C++ в Data Science для новичков