Форум программистов, компьютерный форум, киберфорум
Pascal ABC
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 29.11.2023
Сообщений: 32

Возведение матрицы в степень

29.03.2024, 10:07. Показов 999. Ответов 7

Студворк — интернет-сервис помощи студентам
Возведение матрицы в степень.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure multmatr;
var i,j,k,p:integer;
begin
  for i:=1 to n do
    for j:=1 to i-1 do 
    begin
      p:=b[i,j];
      b[i,j]:=b[j,i];
      b[j,i]:=p;
    end;
  for i:=1 to n do
    for j:=1 to n do
    begin
      p:=0;
      for k:=1 to n do
        p:=p+a[i,k]*b[j,k];
        c[i,j] := p;
    end;
  end;
есть процедура перемножения, но как сделать чтобы она возводила в степень матрицу
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
29.03.2024, 10:07
Ответы с готовыми решениями:

Возведение матрицы в степень.
Следом квадратной матрицы называется сумма элементов, расположенных на главной диагонали. Даны квадратная матрица A порядка m, натуральное...

Возведение в степень
var t1: integer; t2: integer; fi1: double; fi2: double; pn: double; fnp: double; ew1: double; ew2: double; x:longint;

Возведение в степень
Вывести на экран числа a в степени -n, a в степени -n+1, a в степени -n+2, a в степени -1 для заданных вещественного a и натурального n

7
Модератор
10228 / 5516 / 3372
Регистрация: 17.08.2012
Сообщений: 16,868
29.03.2024, 11:32
Но это не совсем процедура перемножения. Матрица b непонятно зачем транспонируется.

Плюс к этому, использование глобальных переменных (в данном случае матриц) - это, мягко говоря, очень плохой стиль программирования. От этого возникают трудно локализуемые ошибки из-за перекрытия областей видимости глобальных и локальных переменных.

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

Чтобы не пришлось делать лишней работы, пожалуйста, напишите задание в том виде, в котором Вам его выдали.
0
Модератор
Эксперт Pascal/DelphiЭксперт NIX
 Аватар для bormant
7810 / 4630 / 2835
Регистрация: 22.11.2013
Сообщений: 13,149
Записей в блоге: 1
29.03.2024, 18:32
Быстрое возведение в степень матрицы
Возвести матрицу А в 15 степень
0
0 / 0 / 0
Регистрация: 29.11.2023
Сообщений: 32
29.03.2024, 22:20  [ТС]
Цитата Сообщение от Cyborg Drone Посмотреть сообщение
Матрица b непонятно зачем транспонируется.
Чтобы программа работала быстрее.
Цитата Сообщение от Cyborg Drone Посмотреть сообщение
напишите задание в том виде, в котором Вам его выдали.
я уже додумал сам алгоритм, спасибо что откликнулись.

Добавлено через 2 минуты

Добавлено через 32 секунды
Цитата Сообщение от bormant Посмотреть сообщение
Быстрое возведение в степень матрицы
Pascal
1
2
3
4
5
6
7
8
9
10
11
procedure mPow(var x: TMatrix; n: Integer);
var t: TMatrix;
begin
  while n>1 do begin
    if Odd(n) then begin
      mMul(t,x,x); mMul(x,x,t);
    end else
      mMul(x,x,x);
    n:=n div 2;
  end;
end;
можете подсказать как это работает или посоветовать где почитать про это?
0
Модератор
10228 / 5516 / 3372
Регистрация: 17.08.2012
Сообщений: 16,868
30.03.2024, 12:13
Цитата Сообщение от Tenmaa Посмотреть сообщение
Чтобы программа работала быстрее.
Добавление на каждой итерации абсолютно лишних N(N+1)/2 перемещений непонятно зачем - это ускорение? Вас никто не обманул?
Цитата Сообщение от Tenmaa Посмотреть сообщение
я уже додумал сам алгоритм
Вы так считаете? Уверены? Точно-точно? Это Вы зря. Я бы не был так уверен.
Цитата Сообщение от Tenmaa Посмотреть сообщение
можете подсказать как это работает
Пусть в степень возводится некое X. Известно следующее свойство степени:

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
X^{b+c}=X^bX^c<br />

Пусть показатель степени есть натуральное число N. Переведём N в двоичную систему счисления (разложим его на сумму степеней числа 2):

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
N=2^0k_0+2^1k_1+2^2k_2+\,...\,+2^{p-1}k_{p-1}+2^pk_p<br />

где 2t - это степени числа 2 (1, 2, 4, 8, 16 и так далее. Не благодарите, всегда Ваш Captain Obvious). Число p на единицу меньше количества значащих двоичных разрядов числа N, а kt есть веса двоичных разрядов, и равны 0 или 1, поскольку СС двоичная. Тогда

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
X^N=X^{2^0k_0+2^1k_1+2^2k_2+\,...\,+2^{p-1}k_{p-1}+2^pk_p}=X^{2^0k_0}X^{2^1k_1}X^{2^2k_2}\cdot \,...\,\cdot X^{2^{p-1}k_{p-1}}X^{2^pk_p}<br />

Это и есть формула быстрого возведения в степень. При обычном возведении в степень требуется N-1 умножений, при быстром - максимум 2(log2(n))+1 умножений. Например: если N=1000, то понадобится всего 15 умножений вместо 999, поскольку 100010=11111010002.

Заметим, что

https://www.cyberforum.ru/cgi-bin/latex.cgi?<br />
X^{2^0}=X;\ \ X^{2^1}=X^2;\ \ X^{2^2}=\left( X^2\right)^2;\ \ X^{2^3}=\left( \left( X^2\right)^2\right)^2;\ \ X^{2^4}=\left( \left( \left( X^2\right)^2\right)^2\right)^2\,...<br />

Обратите внимание на правые части равенств. Видно, что каждое следующее X2t равно квадрату предыдущего.

Вот и алгоритм нарисовался.

Перевод N в двоичную СС можно производить "на лету": если текущее N нечётное, то младший разряд N равен 1, что означает, что kt=1, если число чётное - то kt=0. После делим N нацело на 2, в результате чего младшим станет следующий разряд, и далее по этому новому N можно будет определить kt+1.

Алгоритм:
  1. Сначала присваиваем дополнительной переменной, например, Xn, значение X, и принимаем X=1 (в случае матриц принимаем X=E, где E - единичная матрица).
  2. Затем будем умножать будущий результат X на Xn, если kt=1, либо ничего не делать, если kt=0 (в этом случае 2tkt=0, и сомножитель X2tkt=1, а на 1 умножать смысл умер). После чего вычисляем следующее Xn=(Xn)2, и убираем из N младший разряд.
  3. Повторяем пункт 2), пока в N не кончатся значащие разряды (пока N не станет равным 0).

Tenmaa, В той темпе, откуда Вы взяли код, я накосячил, а вслед за мной - и bormant тоже.
bormant, дружище, дико извиняюсь. Позже отпишусь в ту тему.

Правильно будет, например, так (минимальная тестовая программа):
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const
  m = 5; //размер матрицы
  
type
  TMatrix = array[1..m, 1..m] of real; //тип для матрицы
  
procedure mMul(var x: TMatrix; const y, z: TMatrix); //умножение матриц
var
  i, j, k: integer;
  p: TMatrix;
  t: Real;
begin
  for i := 1 to m do
    for j := 1 to m do
      begin
        t := 0;
        for k := 1 to m do t := t + y[i,k] * z [k,j];
        p[i,j] := t
      end;
  x := p
end;
 
procedure mPow(var x: TMatrix; n: integer); //возведение матрицы x в степень n
var
  xn: TMatrix;
  i, j: integer;
begin
  xn := x; //xn=x^(2k), начальное xn=x^(2^0)=x
  for i := 1 to m do //x=E
    for j := 1 to m do
      if i <> j then x[i,j] := 0 else x[i,j] := 1;
  while n > 0 do //цикл возведения в степень
    begin
      if odd(n) then mMul(x,x,xn); //при единичном младшем разряде умножаем x=x*xn (иначе ничего не делаем)
      mMul(xn,xn,xn); //следующее xn=xn*xn=x^(2^(k+1))
      n := n div 2 //убираем младший разряд из n
    end
end;
 
procedure prn(s: string; const x: TMatrix); //печать матрицы
var
  i, j: integer;
begin
  writeln(s);
  for i := 1 to m do
    begin
      for j := 1 to m do write(x[i,j]:15, ' ');
      writeln
    end
end;
 
var
  x: TMatrix;
  n, i, j: integer;
begin
  randomize;
  for i := 1 to m do //генерация матрицы
    for j := 1 to m do
      x[i, j] := 20 * random - 10;
  prn('Исходная матрица X:', x);
  write('n = ');
  readln(n);
  mPow(x,n);
  prn('Матрица X^n:', x);
end.
1
0 / 0 / 0
Регистрация: 29.11.2023
Сообщений: 32
31.03.2024, 14:12  [ТС]
Цитата Сообщение от Cyborg Drone Посмотреть сообщение
Вы так считаете? Уверены? Точно-точно? Это Вы зря. Я бы не был так уверен.
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const
  n = 3;
  
type matrix = array [1..n, 1..n] of Integer;
 
var
  matr,resmatr: matrix;
  
  power, i, j, k: Integer;
procedure outmat(a:matrix);
var i,j:integer;
begin
for i:=1 to n do
begin
  for j:=1 to n do
  write(a[i,j]:5);
  writeln;
end;
end;
procedure multmatrix(a,b:matrix;var c:matrix);
var i,j,k,p:integer;
begin
  for i:=1 to n do
    for j:=1 to i-1 do 
    begin
      p:=b[i,j];
      b[i,j]:=b[j,i];
      b[j,i]:=p;
    end;
  
  for i:=1 to n do
    for j:=1 to n do
    begin
      c[i,j]:=0;
      for k:=1 to n do
        c[i,j]+=a[i,k]*b[j,k];
        
    end;
end;
 
 
begin
   for i := 1 to n do
     for j := 1 to n do 
       matr[i,j]:=random(10);
   outmat(matr);
 
  Write('степ ');
  ReadLn(power);
 
  for i := 1 to n do
    for j := 1 to n do
      resmatr[i, j] := matr[i,j];
  
  //outmat(resmatr);
  //writeln('-RESULT-');
  for i := 2 to power do
  begin
    multmatrix(resmatr, matr, resmatr);
    //outmat(resmatr);
  end;
 
  WriteLn('рез-т ');
  outmat(resmatr);
end.
0
Модератор
Эксперт Pascal/DelphiЭксперт NIX
 Аватар для bormant
7810 / 4630 / 2835
Регистрация: 22.11.2013
Сообщений: 13,149
Записей в блоге: 1
31.03.2024, 17:53
Tenmaa,
Чтобы в приведенном варианте вычислений от транспонирования был толк, а не одни только тормоза, должно было быть что-то такое:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
type
  TMatrix = array [0..n-1,0..n-1] of Integer;
 
procedure mPow(var r: TMatrix; a: TMatrix; p: Integer);
var
  t: TMatrix;
  i, j, k: Integer;
  x: Integer;
begin
  { r = E }
  for i:=0 to n-1 do for j:=0 to n-1 do r[i,j]:=0;
  for i:=0 to n-1 do r[i,i]:=1;
  { transpose a }
  for i:=0+1 to n-1 do for j:=0 to i-1 do begin
    x:=a[i,j]; a[i,j]:=a[j,i]; a[j,i]:=x;
  end;
  { productions }
  for p:=1 to p do begin
    for i:=0 to n-1 do for j:=0 to n-1 do begin { a - transposed! }
      x:=0; for k:=0 to n-1 do Inc(x,r[i,k]*a[i,k]); t[i,j]:=x;
    end;
    r:=t;
  end;
end;
То же самое по аналогии несложно написать и для быстрого умножения, ибо смешно говорить про скорость, но использовать заведомо более медленный алгоритм.
1
Модератор
Эксперт Pascal/DelphiЭксперт NIX
 Аватар для bormant
7810 / 4630 / 2835
Регистрация: 22.11.2013
Сообщений: 13,149
Записей в блоге: 1
04.04.2024, 16:51
Если правильно путаю, использование транспонированного множителя для быстрого возведения в степень могло быть таким:
Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const n=5;
 
type
  TNum = Real;
  TMatrix = array [0..n-1, 0..n-1] of TNum;
 
procedure mMul_t(var r: TMatrix; const a, bt: TMatrix);
var i, j, k: Integer; t: TNum;
begin
  for i:=n-1 downto 0 do for j:=n-1 downto 0 do begin
    t:=0; for k:=n-1 downto 0 do t:=t+a[i,k]+bt[j,k]; r[i,j]:=t;
  end;
end;
 
procedure mPow(var x: TMatrix; p: Integer);
var
  xn, xt: TMatrix;
  i, j: Integer;
begin
  xn:=x;
  { x=E }
  for i:=n-1 downto 0 do for j:=n-1 downto 0 do x[i,j]:=0;
  for i:=n-1 downto 0 do x[i,i]:=1;
  { productions }
  while p>0 do begin
    for i:=n-1 downto 0 do for j:=n-1 downto 0 do xt[i,j]:=xn[j,i];
    if Odd(p) then mMul_t(x,x,xt);
    if p>1 then mMul_t(xn,xn,xt);
    p:=p div 2;
  end;
end;
стр. 28: исходя из того, что p>1 много дешевле mMul_t(), а количество повторов не сильно велико, пробуем сэкономить вызов mMul_t() на последнем шаге.

Добавлено через 1 минуту
Стоило ли разворачивать циклы (to -> downto) вопрос открытый, стоило бы проверить (не в PascalABC)...
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
04.04.2024, 16:51
Помогаю со студенческими работами здесь

Возведение в степень
есть код: var i, n: integer; var a, y: real; begin writeln('Возведение в степень'); write('Введите основание &gt;&gt;'); ...

Возведение в степень
Возникла проблема с возведением в степень функции y:=sqrt(t+1)*exp(-a*x*t)*cos(t-a), почему-то дает не тот ответ. Если смотреть в мадкаде...

Возведение в степень tg
Привет всем. Столкнулся с небольшой проблемкой в Pascal ABC. Мне нужно: {tg}^{2} z/2. Как это записать на паскалевском языке? ...

Возведение в степень
Возведение в степень По трем натуральным числам a, b и m вычислить значение a в степени b mod m. Входные данные Три натуральных...

Возведение в степень
Используя только операцию * (умножение), только 1 операцию в выражении, минимум переменных Получить: а) x8 б) x10 в) x15 г) x20


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Квантовые алгоритмы и обработка строк в Q#
EggHead 07.06.2025
Квантовые вычисления перевернули наше представление о том, как работать с данными, а Q# стал одним из ключевых языков для разработки квантовых алгоритмов. В традиционых системах мы оперируем битами —. . .
NUnit и C#
UnmanagedCoder 07.06.2025
В . NET существует несколько фреймворков для тестирования: MSTest (встроенный в Visual Studio), xUnit. net (более новый фреймворк) и, собственно, NUnit. Каждый имеет свои преимущества, но NUnit. . .
с++ Что нового?
russiannick 06.06.2025
Продолжаю обзор dev-cpp5. 11. Посмотрев на проекты, предоставленные нам для обучения, становится видно, что они разные по содержащимся файлам где: . dev обязательно присутствует . cpp/ . c один из них. . .
WebAssembly в Kubernetes
Mr. Docker 06.06.2025
WebAssembly изначально разрабатывался как бинарный формат инструкций для виртуальной машины, обеспечивающий высокую производительность в браузерах. Но потенциал технологии оказался гораздо шире - она. . .
Как создать первый микросервис на C# с ASP.NET Core, step by step
stackOverflow 06.06.2025
Если говорить простыми словами, микросервисная архитектура — это подход к разработке, при котором приложение строится как набор небольших, слабо связанных сервисов, каждый из которых отвечает за. . .
Рисование коллайдеров Box2D v2 на Three.js с помощью порта @box2d/core
8Observer8 06.06.2025
Используется порт Box2D v2 под названием @box2d/ core - пакет NPM. Загрузил документацию Box2D v2 на Netlify: https:/ / box2d-v2-docs. netlify. app/ Документацию Box2D v2 можно скачать с официального. . .
Как создать стек в Python
AI_Generated 05.06.2025
Как архитектор с более чем десятилетним опытом работы с Python, я неоднократно убеждался, что знание низкоуровневых механизмов работы стеков дает конкурентное преимущество при решении сложных задач. . . .
Server-Sent Events (SSE) в Node.js
run.dev 05.06.2025
Потоковая передача данных с сервера прямо в браузер стала повседневной потребностью - от биржевых графиков и спортивных трансляций до чатов и умных дашбордов. Много лет разработчики полагались на. . .
Создаем RESTful API на Golang с Fiber
golander 04.06.2025
Я перепробовал десятки фреймворков для создания RESTful API за последние годы, и когда впервые столкнулся с Fiber, понял, что это совсем другой уровень. Нет, я не собираюсь рассказывать сказки о. . .
Как работать с куки в ASP.NET Core
UnmanagedCoder 04.06.2025
Когда я впервые начал работать с куки в ASP. NET Core, меня поразило, насколько отличается работа с ними от классического ASP. NET. В Core все стало более декомпозированным - больше нет удобного. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru
OSZAR »