О программировании
Указанный архив можно скачать там.
Начните чтение с History.pdf.
В архиве вы найдете несколько PDF-файлов с текстами и много кода, повторяющегося в значительной мере. Гиперссылки выделены синим цветом.
Архив следует разгрузить в один каталог и читать PDF с помощью Adobe Reader. При использовании других средств просмотра PDF работоспособность гиперссылок не гарантируется.
Что в этом выпуске
Доведен до ума класс Polynomial с коэффициентами double.
Дальше возник вопрос о многочленах с коэффициентами других типов. Если c коэффициентами типа float проблема решается контекстной заменой,
то для целочисленных типов (включая вычеты по модулю) характерны другие алгебраические свойства. Например, для int нет деления, а вместо него деление с остатком. Для вычетов по непростому модулю нет ни того, ни другого. И еще у этих типов нет округления результатов операций, что позволяет ставить и решать вопрос о делимости многочленов, НОД и НОК.
Получается, что хотя структура объекта одинаковая, набор операций и их реализация существенно зависят от свойств типа коэффициентов. Поэтому пришлось строить наследственное дерево классовых шаблонов:
Общий для всех шаблонов суффикс S означает скалярные типы коэффициентов. Все значения скалярного типа имеют одинаковый размер в оперативной памяти, что позволяет размещать их в памяти в виде сплошного динамического массива и работать с ними через указатели. Такими являются все встроенные числовые типы.
Структура самого объекта (степень и указатель на массив коэффициентов) одинакова для всех шаблонов, но на нижележащих уровнях появляются новые операции над многочленами или другие реализации операций.
В связи с этим появляется много заморочек, борьба с которыми (даже чуть эмоционально) описана в текстах.
Если пользователю нужен только один тип коэффициентов, можно предложить ему — вместо возни с иерархией шаблонов — генератор классов типа Polynomial. Ему следует заполнить небольшую анкету о свойствах типа коэффициентов и получить на выходе .obj-файл с необходимым ему классом многочленов.
Еще одна существенная проблема. Начиная со стандарта C++11, в языке появилась концепция move, иначе называемая семантикой перемещения. Применительно к нашим объектам это означает следующее. Например, в случае операции присваивания коэффициенты исходного многочлена можно не копировать в массив коэффициентов многочлена-копии, а просто передать его во владение копии. При этом надо обеспечить, что исходный многочлен больше не будет использоваться, а его массив коэффициентов не будет удален (динамическая память под ним не будет освобождена). Понятно, что это повышает быстродействие.
Стандартный способ реализации семантики перемещения исполняется продукцией MS. Это очень удобно и дает, я полагаю, хорошие результаты.
Имеющаяся у меня бесплатная система программирования, хоть и датируется 20 годом и все еще в развитии, стандарт C++11 реализует неполностью. В связи с этим было испытано 2 рукодельных способа реализации перемещения — с каждым вариантом проекта. Результаты и обнаруженные проблемы описаны в документах архива.
Дальнейшее направление работы будет связано с составными типами коэффициентов, хранящих свои данные в выделенных участках динамической памяти.