Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 19.09.2015, 12:45   #1
Rhasta-Rhasta
Пользователь
 
Регистрация: 13.09.2015
Сообщений: 16
Сообщение Delphi и работа с матрицами

Здравствуйте.
Не так давно занимаюсь программированием на Delphi, накопился ряд нерешённых пока проблем. По порядку:
Имеется потребность в работе с большим количеством матричных выражений (сложение, умножение матриц, векторов). Для упрощения записи данных операций имеется замечательный инструмент - перегрузка операторов, однако он доступен только для переменных типа Record. Определил типы для вектора и матрицы следующим образом:

Код:
  TV = array of extended;
  TM = array of TV;

  TVect = record
    v: TV;
   private
    function getVCoeff(i: integer): extended; //читать коэффициент
    procedure setVCoeff(i: integer; Num: extended); //записать коэффициент
   public
    class operator Add(Vector1,Vector2: TVect): TVect; //сложение векторов
    property p1[i: integer]: extended read getVCoeff write setVCoeff; default;
  end;

  TMatrix = record
    M: TM;
   private
    function getCoeff(i,j: integer): extended; //читать коэффициент
    procedure setCoeff(i,j: integer; Num: extended); //записать коэффициент
   public
    class operator Add(Matrix1, Matrix2: TMatrix): TMatrix; //сложение матриц
    property p1[i,j: integer]: extended read getCoeff write setCoeff; default;
  end;
1. Существует ли более удобный способ организации данных для матриц и векторов с реализацией возможности перегрузки операторов?

2. Основная проблема при работе с такими типами состоит в том, что для выполнения любой операции над данными требуется обращаться к методу М (например SetLength(MyMatrix.M, NewLength), что очень раздражает. К сожалению, не знаю как выполнить перегрузку стандартных функций и процедур из библиотеки System (процедуры setlength и функций length и high), а переопределение этих функций замещает таковые из System.

3. Отсутствует возможность обратиться к строке матрицы через свойство по-умолчанию (default), так как оно уже занято обращением к коэффициенту.

4. Описанные типы предназначены для работы с матрицами и векторами, наполненными переменными типа extended, существует ли возможность использовать те же типы для работы матрицами и векторами, наполненными комплексными числами? (комплексное число имеет тип record и имеет все необходимые перегруженные операторы).

Последний раз редактировалось Rhasta-Rhasta; 19.09.2015 в 12:53.
Rhasta-Rhasta вне форума Ответить с цитированием
Старый 19.09.2015, 14:01   #2
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

Цитата:
Сообщение от Rhasta-Rhasta Посмотреть сообщение
По порядку:
Имеется потребность в работе с большим количеством матричных выражений (сложение, умножение матриц, векторов).

1. Существует ли более удобный способ организации данных для матриц и векторов с реализацией возможности перегрузки операторов?

2. Основная проблема при работе с такими типами состоит в том, что для выполнения любой операции над данными требуется обращаться к методу М (например SetLength(MyMatrix.M, NewLength), что очень раздражает. К сожалению, не знаю как выполнить перегрузку стандартных функций и процедур из библиотеки System (процедуры setlength и функций length и high), а переопределение этих функций замещает таковые из System.

3. Отсутствует возможность обратиться к строке матрицы через свойство по-умолчанию (default), так как оно уже занято обращением к коэффициенту.

4. Описанные типы предназначены для работы с матрицами и векторами, наполненными переменными типа extended, существует ли возможность использовать те же типы для работы матрицами и векторами, наполненными комплексными числами? (комплексное число имеет тип record и имеет все необходимые перегруженные операторы).
1. Может стоит обратится к указателям? Матрицы же приставляют собой динамические квадратные массивы. Описать их можно так: Matric1: array of array of <тип>; Если они нужны чисто для решения таких задач, то можно применить типы простых или дробных чисел(int64 и real). При чем второе - универсальное.
2. Компилятор должен по умолчанию подгружать все стандартные функции. Вам тут понадобится три модуля: System, Windows, SysUtils, Math.
3,4 - не очень понял.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 19.09.2015, 14:37   #3
Rhasta-Rhasta
Пользователь
 
Регистрация: 13.09.2015
Сообщений: 16
По умолчанию

1. Указатели пробовал использовать, получается неудобно: такой подход вынуждает для каждой матрицы прописывать MyPoiner:=@MyMatrix.M, что при большом количестве матриц весьма напряжно. Тип extended трогать не будем: нужна высокая точность.
2. Он и подгружает, проблемы появляются если переопределить функции из стандартной библиотеки (к ним тогда приходится добираться через System).
3. Попробую переформулировать: описанный тип позволяет обращаться за чтением и записью к элементу матрицы MyMatrix[i,j] через свойство по-умолчанию; на уровне логики хотелось бы, чтобы объект MyMatrix[i] имел тип TVect, но, как я понял, более одного свойства default определить нельзя.
4. Чем и как нужно дополнить тип, чтобы иметь возможность наполнять матрицы не только переменными типа extended, но и переменными другого типа (в моём случае это комплексные числа, для них определены все необходимые перегруженные операторы)? И возможно ли это в принципе?
Надеюсь, пояснил..

Последний раз редактировалось Rhasta-Rhasta; 19.09.2015 в 14:50.
Rhasta-Rhasta вне форума Ответить с цитированием
Старый 19.09.2015, 18:33   #4
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
Вопрос

Цитата:
Сообщение от Rhasta-Rhasta Посмотреть сообщение
1. Указатели пробовал использовать, получается неудобно: такой подход вынуждает для каждой матрицы прописывать MyPoiner:=@MyMatrix.M, что при большом количестве матриц весьма напряжно. Тип extended трогать не будем: нужна высокая точность.
2. Он и подгружает, проблемы появляются если переопределить функции из стандартной библиотеки (к ним тогда приходится добираться через System).
3. Попробую переформулировать: описанный тип позволяет обращаться за чтением и записью к элементу матрицы MyMatrix[i,j] через свойство по-умолчанию; на уровне логики хотелось бы, чтобы объект MyMatrix[i] имел тип TVect, но, как я понял, более одного свойства default определить нельзя.
4. Чем и как нужно дополнить тип, чтобы иметь возможность наполнять матрицы не только переменными типа extended, но и переменными другого типа (в моём случае это комплексные числа, для них определены все необходимые перегруженные операторы)? И возможно ли это в принципе?
Надеюсь, пояснил..
Мне вот интересно, какая точность именно нужна. Физики/инженеры рассчитывают с точностью 3 знака.
А на счет типа можно записать массив указателей на запись TVector.
Скажем так:
Код:
TVector = record 
X: Integer;
Y: Integer;
Z: Integer;
Distance: Integer; //длина вектора
end;
PVector: TVector^;
Vectors: array of PVector;
4. В программирование есть только несколько типов: Целое число, Дробное число(с знаками после запятой), Символ, Указатель, Байт, Объект, Запись и, наконец, Массив. А так же пользовательские типы(это типы для которых значение специально определенно программистом). Я почитал о комплексных числах и в стандартном представление - это три отдельных числа. Первые два - это любые числа. А мнимое число равно только 0 или 1. Тот самый record, только общий для комплексов.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 19.09.2015, 19:09   #5
Rhasta-Rhasta
Пользователь
 
Регистрация: 13.09.2015
Сообщений: 16
По умолчанию

Смысл высокой точности не в том, чтобы из конечного результата извлечь десяток знаков после запятой, а в том, что итерационный мат. метод может терять сходимость при недостаточном количестве знаков после запятой.
Цитата:
TVector = record
X: Integer;
Y: Integer;
Z: Integer;
Distance: Integer; //длина вектора
end;
PVector: TVector^;
Vectors: array of PVector;
Вектор из трёх координат + длина вектора? Зачем? Прошу заметить, что объект "вектор" не обязан иметь размерность три, а может иметь абсолютно произвольную размерность, также как и матрица не обязана быть квадратной или даже прямоугольной, а вполне спокойно может содержать строки разной длины.

4. Действительно, мне следовало использовать термин "пользовательский тип", но думаю, из контекста это было понятно.
Приведу описание типа "комплексное число":
Код:
Type
 TKind = (Al,Ex);
 TCompNum = Record     {Тип "комплексное число"}
   private
   	CompKind: TKind;   {CompKind - форма представления}
   	a,b: extended;
   	function getKind: TKind;
   	function getRe: extended;
   	function getIm: extended;
   	function getMd: extended;
   	function getPh: extended;
   	procedure setKind(toKind: TKind);
   	procedure setRe(value: extended);
   	procedure setIm(value: extended);
   	procedure setMd(value: extended);
   	procedure setPh(value: extended);
   public
   	class operator Implicit(value: extended): TCompNum;
   	class operator Negative(CompNum: TCompNum): TCompNum;
   	class operator Add(CompNum1, CompNum2: TCompNum): TCompNum;
   	class operator Subtract(CompNum1, CompNum2: TCompNum): TCompNum;
        class operator Multiply(CompNum1, CompNum2: TCompNum): TCompNum;
   	class operator Divide(CompNum1, CompNum2: TCompNum): TCompNum;
   	function Inv: TCompNum;
   	function Conj: TCompNum;
   	property Re: extended read getRe write setRe;
   	property Im: extended read getIm write setIm;
   	property Md: extended read getMd write setMd;
   	property Ph: extended read getPh write setPh;
   	property Kind: TKind read getKind write setKind;
 End;

Последний раз редактировалось Rhasta-Rhasta; 19.09.2015 в 19:18.
Rhasta-Rhasta вне форума Ответить с цитированием
Старый 19.09.2015, 21:28   #6
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

Векторы задаются координатами(а если быть точным, то перемещением по осям координат от начала вектора до конца). Из матрицы я думал, что речь могла идти об определителе.
Компилятор будет матерится на тип. В данном случае можно вообще вынести из записи функции и процедуры, оставив только свойства в виде переменных.
Короче сделать так:
Код:
Type
 TKind = (Al,Ex);
 TCompNum = Record     {Тип "комплексное число"}
CompKind: TKind;   {CompKind - форма представления}
a,b: extended;
Re: extended;
Im: extended;
Md: extended;
Ph: extended;
Для того и созданы записи, чтобы хранить переменные разных типов.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 19.09.2015, 21:44   #7
Rhasta-Rhasta
Пользователь
 
Регистрация: 13.09.2015
Сообщений: 16
По умолчанию

Можно организовать комплексные числа по-разному, спору нет, но в данном случае мне удобно работать с таким представлением. И это всё не относится к изначальной теме поста!
Rhasta-Rhasta вне форума Ответить с цитированием
Старый 20.09.2015, 11:20   #8
саша40
Участник клуба
 
Регистрация: 12.09.2012
Сообщений: 1,030
По умолчанию

Цитата:
Сообщение от Rhasta-Rhasta Посмотреть сообщение
Можно организовать комплексные числа по-разному, спору нет, но в данном случае мне удобно работать с таким представлением. И это всё не относится к изначальной теме поста!
В данном случае тогда вам нужно оформить это в виде объекта, а не записи. Просто мой вариант будет лучше с точки зрения оптимизации. Все важные функции можно вынести и описать уже в unit-е. А функции для изменение значений свойств(в вашей "записи") можно вообще убрать, они просто не понадобятся.
А так мой вариант является логическим решением вашей проблемы: Вам нужно хранить в одной переменной разного типа данные, так по логике и статье в вики, они являются все числами. Вот статья в справочнике по типу Extended: http://www.delphibasics.ru/Extended.php
Так скажите по логике: Что вам ещё надо хранить в этих переменных? Строки? Указатели на объекты и динамические переменные? Объекты? Символы? Байты - это числа от 0 до 255.
Что нужно программисту: Компьютер, Среда программирование, Воображение, Прямые руки, Мозги, Знания этой среды программирования.
Программист-это профессия, а программирование-это моё хобби.
саша40 вне форума Ответить с цитированием
Старый 20.09.2015, 12:02   #9
Rhasta-Rhasta
Пользователь
 
Регистрация: 13.09.2015
Сообщений: 16
Плохо

По всей видимости имеет место недопонимание с моей стороны. Предлагаю откатить чуть назад и по порядку:
1. Есть потребность выполнять векторно-матричные операции с использованием перегруженных операций.
2. Самый минимум, который для этого нужен (в моём видении) выглядит так:
Код:
type  
   TVector = record
     v: array of extended; // или любой другой тип с плавающей запятой
     class operator Add(Vector1,Vector2: TVect): TVect; //для примера приведён только один оператор
   end;

   TMatrix = record
     M: array of array of extended;
     class operator Add(Matrix1, Matrix2: TMatrix): TMatrix; 
   end;
3. Главное неудобство в работе с такими типами состоит в том, что для доступа к непосредственному содержимому вектора или матрицы нужно лезть внутрь записи к методу v и M, например:
Код:
procedure proc;
var
A: TMatrix;
b: TVector;
begin
  setlength(A.M,5,5);
  A.M[2,2]:=99;
  setlength(b.v,5);
  b.v[1]:=71;
end;
4. Понятно, что можно попытаться обойти это неудобство, используя with
Код:
with A do
begin
  setlength(M,5,5);
  M[2,2]:=99;
end;
или указатель
Код:
var
A: TMatrix;
pA: ^<array of array of extended>;
begin
  pA:=@A.M;
  setlength(pA^,5,5);
  pA^[2,2]:=99;
end;
но эти способы выглядят как полумеры, которые при большом количестве объектов типа TMatrix и TVector сильно утяжеляют код.
В связи с этим вопрос: есть ли иной способ упростить доступ к содержимому вектора или матрицы?

Последний раз редактировалось Rhasta-Rhasta; 20.09.2015 в 12:12.
Rhasta-Rhasta вне форума Ответить с цитированием
Старый 20.09.2015, 13:06   #10
JUDAS
фонатик DELPHI
Форумчанин
 
Аватар для JUDAS
 
Регистрация: 14.01.2008
Сообщений: 714
По умолчанию

Цитата:
Сообщение от Rhasta-Rhasta Посмотреть сообщение
По всей видимости имеет место недопонимание с моей стороны. Предлагаю откатить чуть назад и по
....
В связи с этим вопрос: есть ли иной способ упростить доступ к содержимому вектора или матрицы?
Автор, если не нравятся "резиновые" массивы попользуйся работой с памятью напрямую (пример 2-х мерной матрицы)

инициализация
Код:
data : Pointer;
         fsizex, fsizey : integer;
procedure SetSize(sizex, sizey : integer); 
begin
   ReallocMem(data, sizex*sizey*sizeof(extended));
   FillChar(data^, sizex*sizey*sizeof(extended),0);
   fsizex := sizex;
   fsizey := sizey;
end;
Доступ запись
Код:
procedure SetValue(x,y: integer; value :Extended);
begin
   PExtended(integer(data)+(x*fsizex+y)*sizeof(extended))^ := value;
end;
Доступ чтение
Код:
function GetValue(x, y : integer) : extended; 
begin
    result := PExtended(integer(data)+(x*fsizex+y)*sizeof(extended))^;
end;
можно в приватной секйии прописать
Код:
function GetAddress(x,y:integer):PExtended;
begin
    result := PExtended(integer(data)+(x*fsizex+y)*sizeof(extended));
end;
тогда
Код:
function GetValue(x, y : integer) : extended; 
begin
    result := GetAddress(x, y)^;
end;

function SetValue(x,y: integer; value : Extended);
var ref : PExtended;
begin
    ref := GetAddress(x, y);
    ref^ := value;
end;
-----------
кстати автор о птичках, при такой организации класса-структуры, у тебя появляется возможность выполнения пакетных операций используя множество команд процессора XMM
95% сбоев и ошибок приложений, находится в полу метрах от монитора

Последний раз редактировалось JUDAS; 20.09.2015 в 13:09.
JUDAS вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Работа с матрицами (Delphi) Elenachu Помощь студентам 0 15.01.2014 00:25
Работа с Матрицами (Delphi 7) Дмитрий5 Помощь студентам 0 22.12.2011 21:36
Работа с матрицами (Delphi) Вета Помощь студентам 0 15.04.2009 15:37
Работа с матрицами (Delphi) roman09 Помощь студентам 6 11.04.2009 11:32
Работа с матрицами (delphi) Майструк Татьяна Помощь студентам 3 07.04.2009 20:33