Помощь - Поиск - Пользователи - Календарь
Полная версия: Вычислить собственные значения матрицы и вектор
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Shmanich
Задали написать програму вычисления собственных значений матрицы (можно еще и вектора) прямым методом. Поясните пожалуйста, что это за метод такой? Вот этот или нет? У меня есть исходники метода Якоби. Он подойдет в качестве прямого или нет?
Shmanich
В одной книжке нашел код программы, которая как раз вычисляет собственные значения матрицы прямым ходом. Но она не компилируется, компилятор ругается на строку «procedure Secant(var x0, x, e: real; function F:real);», а именно на «function F:real». Подскажите где что пропущено.
Свою процедуру вывода я закомментировал, оставил все как учебнике за исключением своей процедуры ввода матрицы.

Полный код:


program sobst_znach_matr;
{Найти собстсвенное значение матрицы прямым ходом}

uses crt;
const c=10;
 type mat=array [1..c, 1..c] of real;
  var A, B: mat;
      n: integer;
      x0, x, e: real;

{Процедура ввода матрицы}
procedure Matr_Vvod(n: integer; var A:mat);
 var i, j: integer;
 begin
  writeln('Вводите коэфф-ты матpицы A по стpокам нажимая ENTER:');
  for i:=1 to n do
   for j:=1 to n do
    begin
     write ('a[',i,',',j,']='); {Ввод матрицы}
     read(a[i,j]);
    end;
 end;

{Процедура вывода матрицы}
{procedure Matr_Vivod(n: integer; var A:mat);
 var i, j: integer;
  begin
   for i:=1 to n do
    begin
     for j:=1 to n do
      write (a[i, j]:5:3,' ':2); {Вывод матрицы с отступами}
 {     writeln;
    end;
 end;

{Процедура вычисления определителя}
procedure Det(n: integer; var A:mat; var s:real);
 var i, j, k, k1: integer;
            p, r: real;
 begin
  p:=1.0;
   for k:=1 to n-1 do
    begin
     k1:=k+1;
     s:=A[k,k];
     j:=k;
     for i:=k1 to n do
      begin
       r:=A[i,k];
       if abs(r) > abs(s) then
        begin
         s:=r;
         j:=i;
        end;
      end;
     if s=0.0 then exit;
     if j<>p then
      begin
       p:=-p;
        for i:=k to n do
         begin
          r:=A[k,i];
          A[k,i]:=A[j,i];
          A[j,i]:=r;
         end;
      end;
     for j:=k1 to n do
      A[k,j]:=A[k,j] / s;
       for i:=k1 to n do
        begin
         r:=A[i,k];
         for j:=k1 to n do
          A[i,j]:=A[i,j] - A[k,j] * r;
        end;
        p:=p * s;
    end;
    s:=p * A[n,n];
 end;

function F(x:real):real;
 var i, j: integer;
        s: real;
 begin
  for i:=1 to n do
   for j:=1 to n do
    if i=j then
     A[i,i]:=B[i,i] - x
    else
     A[i,j]:=B[i,j];
   Det(n,a,s);
   F:=s;
 end;

{Метод секущих}
procedure Secant(var x0, x, e: real; function F:real);
 var d, y, r: real;
  begin
   r:=x-x0;
   d:=F(x0);
   repeat
    y:=F(x);
    r:=r / (d - y) * y;
    d:=y;
    x:=x + r;
   until abs(r) < e;
  end;

 begin
  clrscr;

  writeln('Вычислить собстывенное значение матрицы.');
  writeln;
{  writeln('Введите кол-во элементов в строке матрицы и нажмите ENTER');
  writeln('(Число элементов в строке будет равно числу элементов в столбце!):');
  readln (n);
  writeln;
  }

  write ('n, x0, x, e :');
  readln (n, x0, x, e);

  Matr_Vvod(n,A); {Ввод матрицы}
  {writeln;
  Matr_Vivod(n,A); {Вывод матрицы}

  Secant(x0,x,e,F);

  writeln ('Lyamda=', x);

 readkey;

end.

Федосеев Павел
Думаю, что нужно объявить тип
Код
type
  TFuncReal=function (x: real): real;

И использовать этот тип при описании функции
Код
procedure Secant(var x0, x, e: real; F: TFuncReal);
Shmanich
Цитата(Федосеев Павел @ 14.04.2013 22:13) *

Думаю, что нужно объявить тип
Код
type
  TFuncReal=function (x: real): real;

И использовать этот тип при описании функции
Код
procedure Secant(var x0, x, e: real; F: TFuncReal);



В таком случае компилятор ругается на строчку

 Secant(x0,x,e,F);



Недопустимая процедура или фукнция.
Федосеев Павел
Читаем главу "Procedural types":
Цитата
From this example, the difference with Turbo Pascal is clear: In Turbo Pascal it isn’t necessary to
use the address operator (@) when assigning a procedural type variable, whereas in Free Pascal it is
required. In case the -MDelphi or -MTP switches are used, the address operator can be dropped.

Или, в данном случае
Код
Secant(x0,x,e,@F);
Shmanich
Цитата(Федосеев Павел @ 14.04.2013 22:58) *

Или, в данном случае
Код
Secant(x0,x,e,@F);



Компилятор прордлжает ругаться на эту строку: "Error 122: Invalid varibale reference". wacko.gif
Shmanich
Похоже, что «function F:real» в строке «procedure Secant(var x0, x, e: real; function F:real);» вовсе и не нужна, она уже объявлена выше, также в строке «Secant(x0,x,e,F);» убрать F. Тогда все компилируется. cool.gif
IUnknown
Цитата
Тогда все компилируется
И в итоге получается слабая тень той программы, которая была написана в книге. Потому что основная цель программы, приведенной в посте №2 - это вызов Secant с ЛЮБОЙ функцией, которая передается в качестве параметра. А то, что получилось у тебя - это тупой вызов вышеописанной функции, строго заданной, и ТОЛЬКО ОДНОЙ. Работать, возможно, будет, но только... О гибкости программы, приведенной в книге здесь и речи уже не идет.

А вообще, по правилам хорошего тона, надо в первом посте указывать, какой у тебя компилятор, а не устраивать тут филиал форума гадалок на кофейной гуще. Хотя о чем это я... Тебе что говори, что нет. Были прецеденты. Всё равно сделаешь по своему, еще и все виноватыми окажутся...
Shmanich
IUnknown

Компилирую в Турбо Паскале 7.0, ест-но. А что толку? Все равно же не скажите как правильно исправить процедуру?! Ой, зануда... Да еще и злопамятный видать! Я вооще забыл о чем мы тогда спорили.

Добавлено через 12 мин.
Меня еще пара вопросов интереует.
Строки

 write ('n, x0, x, e :');
 readln (n, x0, x, e);


предназначены для ввода размера матрицы ”n”, два начальных приближения ”x0”, ”x” к одному из собственных значений матрицы и допустимую погрешность решения характеристического уравнения ”e”. Собственно, что это за начальные приближения ”x0”, ”x”? Охота разобраться.
Для удобства ввода этих параметров я изменил эти две строки на такие:


 writeln('Вычислить собственные значения матрицы.');
 writeln;
 writeln('Введите кол-во элементов в строке матрицы и нажмите ENTER');
 writeln('(Число элементов в строке будет равно числу элементов в столбце!):');
 readln (n);
 writeln;
 writeln('Введите 1-ое начальное приближение "x0" и нажмите ENTER:');
 readln (x0);
 writeln;
 writeln('Введите 2-ое начальное приближение "x" и нажмите ENTER:');
 readln (x);
 writeln;
 writeln('Введите допустимую погрешность и нажмите ENTER:');
 readln (e);
 writeln;

Shmanich
Короче, раз некоторые здесь страдают манией величия и пальцем не пошевелят, чтобы помочь студенту, конечно приходиться перебирать варианты самому dry.gif . Вот нашел подходящий пример:

Метод секущих для решения трансцендентного уравнения f(x) = 0.
x, x0 – два начальных приближения, e - оценка точности получаемого решения, итерационный процесс прекращается при приближении f(x) к нулю меньше, чем на e, x – искомый корень.




function f(x: real): real;

begin

{ конкретизация функции f(x) }

end;

procedure secant(var x0, x: real; e: real);

var

d, y, r: real;

begin

r := x – x0; d := f(x0);

 repeat

y := f(x);

r := r/(d – y)*y; d := y;

x := x + r;

 until abs(r) < e;

end;



Источник

cool.gif

Объявление функции в строке "procedure secant(var x0, x: real; e: real);" тут даже и не пахнет!
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.