IPB
ЛогинПароль:

> ВНИМАНИЕ!

Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.

> Динамические матрицы в процедуре, Есть проблема с динамическими данными...
P-Tigr
сообщение 15.03.2005 22:43
Сообщение #1





Группа: Пользователи
Сообщений: 9
Пол: Мужской

Репутация: -  0  +


Столкнулся с одной проблемой, 2 дня уже бьюсь... что делать - не знаю...
Если коротко, то дело вот в чем.
Я написал процедуру для подсчета определителя матрицы любого порядка (методом Гаусса). И там над матрицей выполняются различные преобразования (складывания строк и т.д.).
Причем - внимание - по условию задания матрица должна быть обязательно динамической!
Процедура работает нормально, определитель находит, НО в то же время изменяет исходную матрицу, а этого нельзя допустить!! Происходит это, как мне кажется, из-за того, что такие матрицы - ссылки на память, поэтому передать ее в процедуру строго по значению нельзя...

Замучился я с этими динамическими структурами... blink.gif
Please, умные люди, help me!
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
 
 Ответить  Открыть новую тему 
Ответов
P-Tigr
сообщение 16.03.2005 18:40
Сообщение #2





Группа: Пользователи
Сообщений: 9
Пол: Мужской

Репутация: -  0  +


ОК, ошибка "Floating divizion by zero" устранена... Мне надо ставить 2 за внимательность... sad.gif

Но осталась 2-я ошибка - "Invalid floating point operation".
Итак, код такой:
function Opred_Gauss(A:TDMAtr):real;
// Описание переменных...
var i,j,jk,ik,new:integer;
   tmp,mnoj,mn1,mn2:real;
   found:boolean;
   AC:TDMAtr;
const  eps = 1e-10;
begin
 { Это то самое копирование матрицы }
 setlength(ac, length(a));
 for i := 0 to pred(length(a)) do
   begin
     setlength(ac[i], length(a[i]));
     for j := 0 to pred(length(a[i])) do
       ac[i, j] := a[i, j]
   end;
 { А теперь - сам алгоритм }
 for i := 0 to high(AC) do
   begin
     if abs(ac[i,i])<eps then
       begin
         result :=0.0;
         exit
       end;
     for j := succ(i) to high(AC) do
       begin
         mnoj:=a[j,i]/a[i,i];
         for jk:=i to high(AC) do
           a[j,jk]:=a[j,jk]-mnoj*a[i,jk];
       end;
   end;
 result := 1.0;
 for i:=1 to high(AC) do
 result:=result*a[i,i];
end;


При данных
1 1 1
1 1 1
1 1 1

возникает вышеописанная ошибка в той же строке
mnoj:=a[j,i]/a[i,i];

Немного помучившись и покапавшись в справочниках, нашел, что это бывает связано с проблемами сопроцессора, и устраняется путем добавления строчки
asm FINIT end;

тогда вместо ошибки возвращается константа NAN.

Окончательный вариант кода выглядит так:

function Opred_Gauss(A:TDMAtr):real;
// Описание переменных...
var i,j,jk,ik,new:integer;
   tmp,mnoj,mn1,mn2:real;
   found:boolean;
   AC:TDMAtr;
const  eps = 1e-10;
begin
 asm FINIT end;

 { Это то самое копирование матрицы }
 setlength(ac, length(a));
 for i := 0 to pred(length(a)) do
   begin
     setlength(ac[i], length(a[i]));
     for j := 0 to pred(length(a[i])) do
       ac[i, j] := a[i, j]
   end;
 { А теперь - сам алгоритм }
 for i := 0 to high(AC) do
   begin
     if abs(ac[i,i])<eps then
       begin
         result :=0.0;
         exit
       end;
     for j := succ(i) to high(AC) do
       begin
         mnoj:=a[j,i]/a[i,i];
         for jk:=i to high(AC) do
           a[j,jk]:=a[j,jk]-mnoj*a[i,jk];
       end;
   end;
 result := 1.0;
 for i:=1 to high(AC) do
 result:=result*a[i,i];
 If Result = NAN then
   Result:=0;
end;
Вот теперь (!) все работает без ошибок... УРА!

Но интересно, есть ли другие пути решения проблемы, без асмы? И отчего она все-таки, эта ошибка?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
volvo
сообщение 16.03.2005 19:16
Сообщение #3


Гость






Цитата(P-Tigr @ 16.03.05 17:40)
ОК, ошибка "Floating divizion by zero" устранена... Мне надо ставить 2 за внимательность... sad.gif

Но осталась 2-я ошибка - "Invalid floating point operation".
Итак, код такой:
function Opred_Gauss(A:TDMAtr):real;
// Описание переменных...
begin
 { Это то самое копирование матрицы }
 ...
 { А теперь - сам алгоритм }
 for i := 0 to high(AC) do
   begin
     if abs(ac[i,i])<eps then
       begin
         result :=0.0;
         exit
       end;
     for j := succ(i) to high(AC) do
       begin
         mnoj:=a[j,i]/a[i,i];  // **** !!! ****
         for jk:=i to high(AC) do
           a[j,jk]:=a[j,jk]-mnoj*a[i,jk]; // **** !!! ****
       end;
   end;
 result := 1.0;
 for i:=1 to high(AC) do
 result:=result*a[i,i];
end;
Вам надо еще раз поставить 2 за "внимательность"... Неужели нельзя было проверить все ли A заменены на AC? Ведь NaN появляется при той же самой ошибке - "деление на 0"... Почему? Проверяется на 0 значение AC, а операция производится с A !!!

В общем, окончательный вариант функции без всякого Асма:
Function Opred_Gauss(A:TDMatr):double;
 const eps=1E-10;
 var
   i,j,jk:integer;
   mnoj:real;
   AC:TDMAtr;
 begin
   setlength(ac, length(a));
   for i := 0 to pred(length(a)) do
     begin
       setlength(ac[i], length(a[i]));
       for j := 0 to length(a[i]) do
         ac[i, j] := a[i, j]
     end;

 for i := 0 to high(AC) do
  begin
    if abs(ac[i,i])<eps then
      begin
        result :=0.0;
        exit
      end;
    for j := succ(i) to high(AC) do
      begin
        mnoj:=ac[j,i]/ac[i,i];
        for jk:=i to high(AC) do
          ac[j,jk]:=ac[j,jk]-mnoj*ac[i,jk];
      end;
  end;
   Result:=1;
   For i:=0 to high(AC) do
     Result:=Result*aC[i,i];
 end;
 К началу страницы 
+ Ответить 

Сообщений в этой теме
P-Tigr   Динамические матрицы в процедуре   15.03.2005 22:43
volvo   P-Tigr, давайте так: вы можете показать код процед...   15.03.2005 22:55
P-Tigr   Вот выдержки из кода: type TDMas = array of rea...   15.03.2005 23:08
P-Tigr   Причем кроме вышеописанной проблемы, при данных до...   15.03.2005 23:10
volvo   Компилятор какой? Delphi или FPC? Турбо-Паскаль от...   15.03.2005 23:11
P-Tigr   Естессно, Delphi ver 6   15.03.2005 23:12
volvo   Естественно, что я переношу тему в раздел Дельфи :...   15.03.2005 23:14
P-Tigr   :D Just OK. I'm sorry, первый раз на форуме...   15.03.2005 23:16
P-Tigr   Thanks, Volvo!   15.03.2005 23:20
volvo   Значит, предложение такое: при входе в функцию выч...   16.03.2005 1:14
P-Tigr   Извините пожалуйста, еще 1 вопрос, помогите разобр...   16.03.2005 6:23
volvo   Это не связано с вводимыми данными... Только с тем...   16.03.2005 9:16
volvo   P-Tigr, небольшая поправочка: Выход за пределы мас...   16.03.2005 11:42
P-Tigr   ОК, ошибка "Floating divizion by zero" у...   16.03.2005 18:40
volvo   Вам надо еще раз поставить 2 за "внимательнос...   16.03.2005 19:16
P-Tigr   Блин... Спасибо за помощь! :) Буду учиться :)   16.03.2005 20:02
$ad!st   вопрос не в тему... а что такое матрица??? вобщем ...   16.03.2005 23:24
klem4   http://forum.pascalnet.ru/index.php?showtopic=2694...   16.03.2005 23:26


 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия 27.07.2025 11:14
Хостинг предоставлен компанией "Веб Сервис Центр" при поддержке компании "ДокЛаб"