Представление полиномов с классами

Объектные требования

Этот пример реализует класс, чтобы представлять полиномы на языке MATLAB®. Конструктивные требования:

  • Поведение класса значения — полиномиальный объект должен вести себя как числовые переменные MATLAB, когда скопировано и передано функциям.

  • Специализированное отображение и индексация

  • Объекты могут быть скаляром только. Специализация отображения и функциональности индексации устраняет нормальное поведение массивов.

  • Арифметические операции

  • Двойной конвертер, упрощающий использование полиномиального объекта с существующими функциями MATLAB, которые принимают числовые входные параметры.

Члены класса DocPolynom

Определение класса задает свойство для хранения данных и задает папку (@DocPolynom), который содержит определение класса.

Следующая таблица обобщает свойства, заданные для класса DocPolynom.

Свойства класса DocPolynom

Имя

Класс

Значение по умолчанию

Описание

coef

double

[]

Вектор полиномиальных коэффициентов [самый высокий порядок... самый низкоуровневый]

Следующая таблица обобщает методы для класса DocPolynom.

Методы класса DocPolynom

Имя

Описание

DocPolynom

Конструктор класса

double

Преобразовывает объект DocPolynom в двойное (то есть, возвращает его коэффициенты в векторе),

char

Создает отформатированное отображение объекта DocPolynom как степени x и используется методом disp

disp

Определяет, как MATLAB отображает объекты DocPolynom на командной строке

subsref

Позволяет вам задать значение для независимой переменной как индекс, получить доступ к свойству coef с записью через точку и методам вызова с записью через точку.

plus

Сложение реализаций объектов DocPolynom

minus

Вычитание реализаций объектов DocPolynom

mtimes

Умножение реализаций объектов DocPolynom

Используя класс DocPolynom

Следующие примеры иллюстрируют основное использование класса DocPolynom.

Создайте объекты DocPolynom представлять следующие полиномы. Аргумент к функции конструктора содержит полиномиальные коэффициенты и.

p1 = DocPolynom([1 0 -2 -5])
p1 =
   x^3 - 2*x - 5
p2 = DocPolynom([2 0 3 2 -7])
p2 =
   2*x^4 + 3*x^2 + 2*x - 7

Найдите корни полинома путем передачи коэффициентов функции roots.

roots(p1.coef)
ans =

   2.0946 + 0.0000i
  -1.0473 + 1.1359i
  -1.0473 - 1.1359i

Добавьте эти два полинома p1 и p2.

MATLAB вызывает метод plus, заданный для класса DocPolynom, когда вы добавляете два объекта DocPolynom.

p1 + p2
ans = 

2*x^4 + x^3 + 3*x^2 - 12

Резюме класса DocPolynom

Пример кодаОбсуждение
classdef DocPolynom

Класс значения, который реализует тип данных для полиномов.

   properties
      coef
   end

Вектор полиномиальных коэффициентов [самый высокий порядок... самый низкоуровневый]

   methods

Для получения общей информации о методах, см. Обычные Методы

      function obj = DocPolynom(c)
         if nargin > 0
            if isa(c,'DocPolynom')
               obj.coef = c.coef;
            else
               obj.coef = c(:).';
            end
         end
      end 

Конструктор класса создает использование объектов:

  • Вектор коэффициентов существующего объекта

  • Вектор коэффициентов передал в качестве аргумента

Смотрите конструктора DocPolynom

      function obj = set.coef(obj,val)
         if ~isa(val,'double')
            error('Coefficients must be doubles')
         end
         ind = find(val(:).'~=0);
         if ~isempty(ind);
            obj.coef = val(ind(1):end);
         else
            obj.coef = val;
         end
      end

Метод установки для свойства coef:

  • Позволяет коэффициенты, только типа double

  • Удаляет начальные нули из вектора коэффициентов.

Смотрите удаляют несоответствующие коэффициенты

      function c = double(obj)
         c = obj.coef;
      end

Преобразуйте объект DocPolynom в double путем возврата коэффициентов.

Смотрите преобразовывают объекты DocPolynom в другие типы

function str = char(obj)
   if all(obj.coef == 0)
      s = '0';
      str = s;
      return
   else
      d = length(obj.coef)-1;
      s = cell(1,d);
      ind = 1;
      for a = obj.coef;
         if a ~= 0;
            if ind ~= 1
               if a > 0
                  s(ind) = {' + '};
                  ind = ind + 1;
               else
                  s(ind) = {' - '};
                  a = -a; 
                  ind = ind + 1;
               end
            end
            if a ~= 1 || d == 0
               if a == -1
                  s(ind) = {'-'};
                  ind = ind + 1;
               else
                  s(ind) = {num2str(a)};
                  ind = ind + 1;
                  if d > 0
                     s(ind) = {'*'};
                     ind = ind + 1;
                  end
               end
            end
            if d >= 2
               s(ind) = {['x^' int2str(d)]};
               ind = ind + 1;
            elseif d == 1
               s(ind) = {'x'};
               ind = ind + 1;
            end
         end
         d = d - 1;
      end
   end
   str = [s{:}];
end

Преобразуйте объект DocPolynom в char, который представляет выражение:

y = f (x)

Смотрите преобразовывают объекты DocPolynom в другие типы

      function disp(obj)
         c = char(obj);
         if iscell(c)
            disp(['     ' c{:}])
         else
            disp(c)
         end
      end 

Перегрузка функция disp. Экранные объекты как вывод метода char.

Для получения информации об этом коде смотрите Перегрузку disp для DocPolynom

      function dispPoly(obj,x)
         p = char(obj);
         e = @(x)eval(p);
         y = zeros(length(x));
         disp(['y = ',p])
         for k = 1:length(x)
            y(k) = e(x(k));
            disp(['  ',num2str(y(k)),...
                  ' = f(x = ',...
                  num2str(x(k)),')'])
         end
      end

Возвратите выполненное выражение с отформатированным выводом.

Использование вывод метода char, чтобы оценить полином по заданным значениям независимой переменной.

Для получения информации об этом коде смотрите Отображение Выполненное Выражение

      function b = subsref(a,s)
         switch s(1).type
            case '()'
               ind = s.subs{:};
               b = polyval(a.coef,ind);
            case '.'
               switch s(1).subs
                  case 'coef'
                     b = a.coef;
                  case 'disp'
                     disp(a)
                  otherwise
                     if length(s)>1
                        b = a.(s(1).subs)(s(2).subs{:});
                     else
                        b = a.(s.subs);
                     end
               end
            otherwise
               error('Specify value for x as obj(x)')
         end
      end

Переопределите индексированную ссылку для объектов DocPolynom.

Для получения информации об этом коде смотрите, Переопределяют Индексируемую Ссылку

      function r = plus(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         k = length(obj2.coef) - length(obj1.coef);
         zp = zeros(1,k);
         zm = zeros(1,-k);
         r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]);
      end

      function r = minus(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         k = length(obj2.coef) - length(obj1.coef);
         zp = zeros(1,k);
         zm = zeros(1,-k);
         r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]);
      end

      function r = mtimes(obj1,obj2)
         obj1 = DocPolynom(obj1);
         obj2 = DocPolynom(obj2);
         r = DocPolynom(conv(obj1.coef,obj2.coef));
      end
   end

Задайте три арифметических оператора:

  • Полиномиальное сложение

  • Полиномиальное вычитание

  • Умножение полиномов

Для получения информации об этом коде смотрите, Задают Арифметические операторы.

Для получения общей информации об определении операторов, см. Перегрузку операторов

   end
end

Операторы end для methods и для classdef.

 Расширьтесь для кода класса

Конструктор DocPolynom

Следующая функция является конструктором класса DocPolynom, который находится в файле @DocPolynom/DocPolynom.m:

methods
   function obj = DocPolynom(c)
      if isa(c,'DocPolynom')
         obj.coef = c.coef;
      else
         obj.coef = c(:).';
      end
   end 
end

Конструктор, вызывающий синтаксис

Это возможно всему конструктору DocPolynom с двумя различными аргументами:

  • Входной параметр является объектом DocPolynom — Если вы вызываете функцию конструктора с входным параметром, который уже является объектом DocPolynom, конструктор возвращает новый объект DocPolynom с теми же коэффициентами как входной параметр. Функция isa проверяет на этот вход.

  • Входной параметр является вектором коэффициентов — Если входной параметр не является объектом DocPolynom, конструктор пытается изменить значения в вектор и присвоить их свойству coef.

    Метод набора свойств coef ограничивает значения свойств, удваивается. Смотрите Удаляют Несоответствующие Коэффициенты для описания метода набора свойств.

Использование в качестве примера конструктора DocPolynom является оператором:

p = DocPolynom([1 0 -2 -5])
p = 
   x^3 - 2*x -5

Этот оператор создает экземпляр класса DocPolynom с заданными коэффициентами. Обратите внимание на то, что отображение объекта показывает эквивалентный полином с помощью синтаксиса языка MATLAB. Класс DocPolynom реализует это отображение с помощью методов класса char и disp.

Удаление несоответствующих коэффициентов

Программное обеспечение MATLAB представляет полиномы как векторы - строки, содержащие коэффициенты, упорядоченные убывающими степенями. Нули в векторе коэффициентов представляют условия, которые выпадают из полинома. Начальные нули, поэтому, могут быть проигнорированы при формировании полинома.

Некоторые методы класса DocPolynom используют длину вектора коэффициентов, чтобы определить степень полинома. Полезно, поэтому, удалить начальные нули из вектора коэффициентов так, чтобы его длина представляла истинное значение.

Класс DocPolynom хранит вектор коэффициентов в свойстве, которое использует метод установки удалить начальные нули из заданных коэффициентов прежде, чем установить значение свойства.

methods
   function obj = set.coef(obj,val)
      if ~isa(val,'double')
         error('Coefficients must be doubles')
      end
      ind = find(val(:).'~=0);
      if ~isempty(ind);
         obj.coef = val(ind(1):end);
      else
         obj.coef = val;
      end
   end
end

Преобразование объектов DocPolynom в другие типы

Класс DocPolynom задает два метода, чтобы преобразовать объекты DocPolynom в другие классы:

  • 'double' Преобразовывает в двойной числовой тип, таким образом, функции могут выполнить математические операции на коэффициентах.

  • 'char' Преобразовывает в символы, используемые к формату вывода для отображения в командном окне

Двойной конвертер

Двойной метод конвертера для класса DocPolynom просто возвращает вектор коэффициентов:

methods
   function c = double(obj)
      c = obj.coef;
   end
end 

Для объекта DocPolynom p:

p = DocPolynom([1 0 -2 -5]);

оператор:

c = double(p)

возвращается:

c=
    1     0    -2    -5

который имеет класс double:

class(c)
ans = 
   double

Символьный конвертер

Метод char производит вектор char, который представляет полином, отображенный как степени x. Возвращенный вектор char является синтаксически правильным выражением MATLAB.

Метод char использует массив ячеек, чтобы собрать компоненты вектора char, которые составляют отображенный полином.

Метод disp использует метод char, чтобы отформатировать объект DocPolynom для отображения. Метод evalPoly использует char, чтобы создать выражение MATLAB, чтобы оценить.

Пользователи объектов DocPolynom вряд ли вызовут char или методы disp непосредственно, но эти методы позволяют классу DocPolynom вести себя как другие классы данных в MATLAB.

Вот метод char.

methods
   function str = char(obj)
      if all(obj.coef == 0)
         s = '0';
         str = s;
         return
      else
         d = length(obj.coef)-1;
         s = cell(1,d);
         ind = 1;
         for a = obj.coef;
            if a ~= 0;
               if ind ~= 1
                  if a > 0
                     s(ind) = {' + '};
                     ind = ind + 1;
                  else
                     s(ind) = {' - '};
                     a = -a; 
                     ind = ind + 1;
                  end
               end
               if a ~= 1 || d == 0
                  if a == -1
                     s(ind) = {'-'};
                     ind = ind + 1;
                  else
                     s(ind) = {num2str(a)};
                     ind = ind + 1;
                     if d > 0
                        s(ind) = {'*'};
                        ind = ind + 1;
                     end
                  end
               end
               if d >= 2
                  s(ind) = {['x^' int2str(d)]};
                  ind = ind + 1;
               elseif d == 1
                  s(ind) = {'x'};
                  ind = ind + 1;
               end
            end
            d = d - 1;
         end
      end
      str = [s{:}];
   end
end

Перегрузка disp для DocPolynom

Обеспечить более полезное отображение объектов DocPolynom, этот класс перегрузки disp в определении класса.

Этот метод disp полагается на метод char, чтобы произвести текстовое представление полинома, который это затем отображает на экране.

Метод char возвращает массив ячеек или символьный '0', если коэффициенты являются всем нулем.

methods
   function disp(obj)
      c = char(obj);
      if iscell(c)
         disp(['     ' c{:}])
      else
         disp(c)
      end
   end
end 

Когда Вызовы MATLAB disp Метод

Оператор:

p = DocPolynom([1 0 -2 -5])

создает объект DocPolynom. Поскольку оператор не отключен с точкой с запятой, получившийся вывод отображен на командной строке:

p =
    x^3 - 2*x - 5

Отображение оцененного выражения

Метод конвертера char формирует выражение MATLAB для полинома, представленного объектом DocPolynom. Метод dispPoly выполняет выражение, возвращенное методом char с заданным значением для x.

methods
   function dispPoly(obj,x)
      p = char(obj);
      e = @(x)eval(p);
      y = zeros(length(x));
      disp(['y = ',p])
      for k = 1:length(x)
         y(k) = e(x(k));
          disp(['  ',num2str(y(k)),...
               ' = f(x = ',...
               num2str(x(k)),')'])
      end
   end
end

Создайте объект DocPolynom p:

p = DocPolynom([1 0 -2 -5])
p = 

x^3 - 2*x - 5

Оцените полином в x, равном трем значениям, [3 5 9]:

dispPoly(p,[3 5 9])
y = x^3 - 2*x - 5
  16 = f(x = 3)
  110 = f(x = 5)
  706 = f(x = 9)

Переопределение индексируемой ссылки

Класс DocPolynom переопределяет индексированную ссылку, чтобы поддержать использование объектов, представляющих полиномы. В классе DocPolynom преобразованная в нижний индекс ссылка на объект вызывает оценку полинома со значением независимой переменной, равной индексу.

Например, учитывая следующий полином:

Создайте объект DocPolynom p:

p = DocPolynom([1 0 -2 -5])
p =
    x^3 - 2*x - 5

Следующее преобразованное в нижний индекс выражение оценивает значение полинома в x = 3 и в x = 4 и возвращает получившиеся значения:

p([3 4])
ans =
    16   51

Индексируемые цели исходного проекта

Переопределите значение по умолчанию преобразованное в нижний индекс ссылочное поведение путем реализации метода subsref.

Если класс задает метод subsref, MATLAB вызывает этот метод для объектов этого класса каждый раз, когда преобразованная в нижний индекс ссылка происходит. Метод subsref должен задать все индексируемые ссылочные поведения, не только конкретный случай, который вы хотите изменить.

Метод subsref DocPolynom реализует следующие поведения:

  • p(x = [a1...an]) — Оцените полином в x = a.

  • p.coef — Доступ к значению свойства coef

  • p.disp — Отобразите полином как выражение MATLAB, не присваивая вывод.

  • obj = p.method(args) — Используйте запись через точку, чтобы вызвать аргументы методов и возвратить измененный объект.

  • obj = p.method — Используйте запись через точку, чтобы вызвать методы без аргументов и возвратить измененный объект.

детали реализации subsref

Метод subsref перегружает функцию subsref.

Например, рассмотрите вызов функции polyval:

p = DocPolynom([1 0 -2 -5])
p = 
     x^3 - 2*x - 5
polyval(p.coef,[3 5 7])
ans =
    16   110   324

Функция polyval требует:

  • Полиномиальные коэффициенты

  • Значения независимой переменной, в которой можно оценить полином

Функция polyval возвращает значение f(x) в этих значениях. subsref вызывает polyval через операторы:

case '()'
   ind = s.subs{:};
   b = polyval(a.coef,ind);

При реализации subsref, чтобы поддержать вызов метода с аргументами с помощью записи через точку, и type и поля структуры subs содержат несколько элементов.

Метод subsref реализует всю преобразованную в нижний индекс ссылку явным образом, как показывают в следующем листинге кода.

methods
   function b = subsref(a,s)
      switch s(1).type
         case '()'
            ind = s.subs{:};
            b = polyval(a.coef,ind);
         case '.'
            switch s(1).subs
               case 'coef'
                  b = a.coef;
               case 'disp'
                  disp(a)
               otherwise
                  if length(s)>1
                     b = a.(s(1).subs)(s(2).subs{:});
                  else
                     b = a.(s.subs);
                  end
            end
         otherwise
            error('Specify value for x as obj(x)')
      end
   end
end

Определение арифметических операторов

Несколько арифметических операций значимы на полиномах. Класс DocPolynom реализует эти методы:

Метод и синтаксис

Реализованный оператор

plus(a,b)

Сложение

minus(a,b)

Вычитание

mtimes(a,b)

Умножение матриц

При перегрузке арифметических операторов рассмотрите типы данных, которые необходимо поддержать. plus, minus, andmtimes методы заданы для класса DocPolynom, чтобы обработать сложение, вычитание и умножение на DocPolynomDocPolynom и DocPolynom — комбинации double операндов.

Определение + оператор

Если или p или q являются объектом DocPolynom, этим выражением:

p + q

Генерирует вызов функционального @DocPolynom/plus, если другой объект не имеет более высокого приоритета.

Следующий метод перегружает plus (+) оператор для класса DocPolynom:

methods
   function r = plus(obj1,obj2)
      obj1 = DocPolynom(obj1);
      obj2 = DocPolynom(obj2);
      k = length(obj2.coef) - length(obj1.coef);
      zp = zeros(1,k);
      zm = zeros(1,-k);
      r = DocPolynom([zp,obj1.coef] + [zm,obj2.coef]);
   end
end 

Вот то, как функция работает:

  • Гарантируйте, что оба входных параметра являются объектами DocPolynom так, чтобы выражения такой как

    p + 1
    

    это включает и DocPolynom и double, работает правильно.

  • Доступ к этим двум векторам коэффициентов и, при необходимости, заполняет одного из них с нулями, чтобы сделать обоих той же длиной. Фактическое сложение является просто векторной суммой этих двух векторов коэффициентов.

  • Вызовите конструктора DocPolynom, чтобы создать правильно типизированный объект, который является результатом добавления полиномов.

Задайте оператор -

Реализуйте оператор minus (-) с помощью того же подхода в качестве plus (+) оператор.

Метод minus вычисляет p - q. Доминирующий аргумент должен быть объектом DocPolynom.

methods
   function r = minus(obj1,obj2)
      obj1 = DocPolynom(obj1);
      obj2 = DocPolynom(obj2);
      k = length(obj2.coef) - length(obj1.coef);
      zp = zeros(1,k);
      zm = zeros(1,-k);
      r = DocPolynom([zp,obj1.coef] - [zm,obj2.coef]);
   end
end 

Определение оператора *

Реализуйте метод mtimes, чтобы вычислить продукт p*q. Метод mtimes реализует умножение матриц, поскольку умножение двух полиномов является сверткой (conv) их векторов коэффициентов:

methods
   function r = mtimes(obj1,obj2)
      obj1 = DocPolynom(obj1);
      obj2 = DocPolynom(obj2);
      r = DocPolynom(conv(obj1.coef,obj2.coef));
   end
end 

Используя арифметические операторы

Учитывая объект DocPolynom:

p = DocPolynom([1 0 -2 -5]);

Следующие две арифметических операции вызывают plus DocPolynom и методы mtimes:

q = p+1;
r = p*q;

произвести

q = 
    x^3 - 2*x - 4

r =
x^6 - 4*x^4 - 9*x^3 + 4*x^2 + 18*x + 20
Для просмотра документации необходимо авторизоваться на сайте