21 / 4 / 2
Регистрация: 07.01.2015
Сообщений: 45
1

Возведение большой матрицы, читаемой с файла, в степень N, и запись обратно в файл на C#

07.01.2015, 20:34. Показов 1331. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго времени. Очень нужно написать программу на C#, которая прочитает с файла огромную матрицу с вещественными числами (допустим, 1000 на 1000), возвести её в степень N, и результат записать в новый файл. Вот так... Думал, сам напишу, убил кучу времени, и теперь, от безысходности, пишу тут. Помогите пожалуйста. За ранее благодарен всем, кто уделит время.
И с Рождеством всех, ребята. =)
P.S.: это нужно делать в консольном приложении. Очень срочно.

Добавлено через 1 минуту
Пример матрицы тут можно взять (363х363):
http://rghost.ru/60192711
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.01.2015, 20:34
Ответы с готовыми решениями:

Возведение числа в степень за минимальное количество умножений, не используя возведение в степень (в чем ошибка?)
должно число подводиться в степень за минимальное кол умножения не используя возведение в степень....

Написать программу с тремя потоками: чтение из файла, возведение в квадрат, запись в файл
Нужно написать программу с 3-мя потоками: чтение из файла, возведение в квадрат, запись в файл...

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

Возведение матрицы в степень
ребятка,помогите разобраться,ыскакует куча ошибок(надо вывести в степень матрицу #include...

12
foo();
886 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
07.01.2015, 22:33 2
МВлад, алгоритм мудреный, но вроде работает
C#
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
static int[,] MatrixPower(int[,] matrix, int power)
{
    int l = matrix.GetLength(0);
    if (matrix.GetLength(1) != l)
        throw new ArgumentException("matrix");
    int[,] result = new int[l, l];
    for(int i = 0; i < l; i++)
        for(int j = 0; j < l; j++)
        {
            int sum = 0;
            var ind = new int[power - 1];
            while(ind[0] != l)
            {
                int el = matrix[i, ind[0]];
                for (int k = 1; k < power - 1; k++)
                    el *= matrix[ind[k - 1], ind[k]];
                el *= matrix[ind[power - 2], j];
                sum += el;
                int m = power - 2;
                while(++ind[m]==l && m > 0)
                {
                    ind[m--] = 0;
                }
            }
            result[i, j] = sum;
        }
    return result;
}
0
2080 / 1238 / 464
Регистрация: 20.12.2014
Сообщений: 3,237
07.01.2015, 22:35 3
Посмотрите здесь, может быть подойдет:
http://easylab.net.ua/massivyi... tritsami-1
или здесь:
Возведение булевых матриц в степень
0
foo();
886 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
07.01.2015, 22:57 4
МВлад, вот еще вариант, который проще понять, рекурсивный
C#
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
static int[,] MatrixPower2(int[,] matrix, uint power)
{
    int l = matrix.GetLength(0);
    if (matrix.GetLength(1) != l)
        throw new ArgumentException();
    var result = new int[l, l];
    if(power == 0)
    {
        for (int i = 0; i < l; i++)
            result[i, i] = 1;
        return result;
    }
    else if (power == 1)
    {
        return matrix;
    }
    result = MatrixPower2(Multiply(matrix, matrix), power / 2);
    if (power % 2 != 0)
        result = Multiply(result, matrix);
    return result;
}
static int[,] Multiply(int[,] m1, int[,] m2)
{
    int l = m1.GetLength(1);
    if (m2.GetLength(0) != l)
        throw new ArgumentException();
    var result = new int[m1.GetLength(0), m2.GetLength(1)];
    for (int i = 0; i < m1.GetLength(0); i++)
        for (int j = 0; j < m2.GetLength(1); j++)
        {
            int sum = 0;
            for (int k = 0; k < l; k++)
                sum += m1[i, k] * m2[k, j];
            result[i, j] = sum;
        }
    return result;
}
1
21 / 4 / 2
Регистрация: 07.01.2015
Сообщений: 45
08.01.2015, 00:37  [ТС] 5
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
Console.WriteLine("Введите размерность матрицы:");
int n = Convert.ToInt32(Console.ReadLine());
var a = new int[n, n];
int i, j;
for (i = 0; i < n; i++)
{
    for (j = 0; j < n; j++)
    {
        Console.Write("Введите элемент [" + i + "][" + j + "]: ");
        a[i, j] = Convert.ToInt32(Console.ReadLine());
     }
}
Console.WriteLine("\n");
int power = 2;
MatrixPower2(a, power);
...
Видимо, я что-то делаю не так, да? Неправильно массив заполнил? Или, скорее всего, неправильно передал? Ибо ответ неправильный он выдаёт. Не подскажете, в чём провинился?
0
25 / 25 / 10
Регистрация: 14.12.2014
Сообщений: 110
08.01.2015, 00:54 6
http://rghost.ru/60197862
Вот. Сохранение переделай, а том я с ним провозился, но сохраняет не так как нада (с тегами).

Добавлено через 1 минуту
Блюааа. Я сделал в форме... Не заметил про консоль...
1
21 / 4 / 2
Регистрация: 07.01.2015
Сообщений: 45
08.01.2015, 01:23  [ТС] 7
Ничего, я хоть на алгоритм посмотрю. Огромное Вам спасибо за такую работу большую!

Добавлено через 10 минут
Не, что-то там совсем не то...
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
08.01.2015, 03:01 8
Лучший ответ Сообщение было отмечено МВлад как решение

Решение

C#
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
namespace ConsoleApplication18
{
    public class Matrix : IEnumerable<double>
    {
        const string DimentionExceptionMessage = "Invalid matrix dimentions";
        public static Matrix GetE(int n)
        {
            var result = new Matrix(n, n);
            for (int i = 0; i < n; i++)
            {
                result[i, i] = 1.0;
            }
            return result;
        }
 
        private readonly double[,] _value;
 
        public Matrix(int rows, int cols)
            : this(new double[rows, cols])
        {
        }
 
        public Matrix(double[,] value)
        {
            _value = (double[,])value.Clone();
        }
 
        public static Matrix operator *(Matrix one, Matrix other)
        {
            return new Matrix(Multiply(one._value, other._value));
        }
 
        public static Matrix operator *(double scalar, Matrix matrix)
        {
            var result = (double[,])matrix._value.Clone();
            for (int i = 0; i < result.GetLength(0); i++)
            {
                for (int j = 0; j < result.GetLength(1); j++)
                {
                    result[i, j] *= scalar;
                }
            }
            return result;
        }
 
        public static Matrix operator *(Matrix matrix, double scalar)
        {
            return scalar * matrix;
        }
 
        public static Matrix operator +(Matrix one, Matrix another)
        {
            return GetMatrix(one, another, 1);
        }
 
        public static Matrix operator -(Matrix one, Matrix another)
        {
            return GetMatrix(one, another, -1);
        }
 
        private static Matrix GetMatrix(Matrix one, Matrix another, int sign)
        {
            var m = GetDim(one, another, 0);
            int n = GetDim(one, another, 1);
            var res = new double[m, n];
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    res[i, j] = one[i, j] + another[i, j] * sign;
                }
            }
            return new Matrix(res);
        }
 
        private static int GetDim(Matrix one, Matrix another, int dim)
        {
            int dimOne = one._value.GetLength(dim);
            int dimAnother = another._value.GetLength(dim);
 
            if (dimOne != dimAnother)
            {
 
                throw new ArgumentException(DimentionExceptionMessage);
            }
            return dimOne;
        }
 
        private int GetDimIfSquare()
        {
            int x = _value.GetLength(0);
            int y = _value.GetLength(1);
            if (x != y)
            {
                throw new ArgumentException(DimentionExceptionMessage);
            }
            return x;
        }
 
        public static Matrix operator /(Matrix matrix, double scalar)
        {
            return matrix * (1.0 / scalar);
        }
 
        public double this[int i, int j]
        {
            get { return _value[i, j]; }
            set { _value[i, j] = value; }
        }
 
        public IEnumerator<double> GetEnumerator()
        {
            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (double d in _value)
            {
                yield return d;
            }
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        public static implicit operator Matrix(double[,] doubles)
        {
            return new Matrix(doubles);
        }
 
        public static explicit operator double[,](Matrix matrix)
        {
            return matrix._value;
        }
 
        private static double[,] Multiply(double[,] a, double[,] b)
        {
            if (a.GetLength(1) != b.GetLength(0))
                throw new ArgumentException(DimentionExceptionMessage);
            var result = new double[a.GetLength(0), b.GetLength(1)];
            Parallel.For(0, a.GetLength(0), i =>
            {
                for (int j = 0; j < b.GetLength(1); j++)
                    result[i, j] = MultiplyR(a, b, i, j);
            });
            return result;
        }
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static double MultiplyR(double[,] a, double[,] b, int i, int j)
        {
            double result = 0;
            for (int k = 0; k < a.GetLength(1); k++)
                result += a[i, k] * b[k, j];
            return result;
        }
 
        public int GetLength(int dim)
        {
            return _value.GetLength(dim);
        }
 
        public Matrix Pow(int power)
        {
            int dim = GetDimIfSquare();
            var result = GetE(dim);
            var tmp = this;
            while (power != 0)
            {
                if (power % 2 != 0)
                {
                    result *= tmp;
                    power -= 1;
                }
                tmp *= tmp;
                power /= 2;
            }
            return result;
        }
    }
}
Добавлено через 44 секунды
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
        static void Main(string[] args)
        {
            double[,] a =
            {
                {1, 2},
                {3, 4}
            };
            var matrix = new Matrix(a);
            var pow = matrix.Pow(5);
            for (int i = 0; i < pow.GetLength(0); i++)
            {
                for (int j = 0; j < pow.GetLength(1); j++)
                {
                    Console.Write(pow[i,j] + " ");
                }
                Console.WriteLine();
            }
        }
Добавлено через 10 минут
Возведение вашего файла в 256 степень например:
C#
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
using System;
using System.IO;
 
namespace ConsoleApplication18
{
    class Program
    {
        static void Main()
        {
            var a = GetMatrixFromFile("test1.A");
            
            var matrix = new Matrix(a);
            var pow = matrix.Pow(256);
            using (var sw = new StreamWriter("result.txt"))
            {
                for (int i = 0; i < pow.GetLength(0); i++)
                {
                    for (int j = 0; j < pow.GetLength(1); j++)
                    {
                        sw.Write(pow[i, j] + " ");
                    }
                    sw.WriteLine();
                }
            }
        }
 
        private static double[,] GetMatrixFromFile(string path)
        {
            string[] lines = File.ReadAllLines(path);
            double[,] a = new double[lines.Length, lines.Length];
            
            for (int i = 0; i < lines.Length; i++)
            {
                var split = lines[i].Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
                for (int j = 0; j < lines.Length; j++)
                {
                    a[i, j] = double.Parse(split[j]);
                }
            }
            return a;
        }
    }
}
1
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
08.01.2015, 04:14 9
После небольших оптимизаций лично на моем компе обсчитывает 256 степень этой матрицы за 4 с небольшим секунд:
C#
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
 
namespace ConsoleApplication18
{
    public class Matrix : IEnumerable<double>
    {
        const string DimentionExceptionMessage = "Invalid matrix dimentions";
        public static Matrix GetE(int n)
        {
            var result = new Matrix(n, n);
            for (int i = 0; i < n; i++)
            {
                result[i, i] = 1.0;
            }
            return result;
        }
 
        private readonly double[,] _value;
 
        public Matrix(int rows, int cols)
            : this(new double[rows, cols])
        {
        }
 
        public Matrix(double[,] value)
        {
            _value = (double[,])value.Clone();
        }
 
        public static Matrix operator *(Matrix one, Matrix other)
        {
            return new Matrix(Multiply(one._value, other._value));
        }
 
        public static Matrix operator *(double scalar, Matrix matrix)
        {
            var result = (double[,])matrix._value.Clone();
            for (int i = 0; i < result.GetLength(0); i++)
            {
                for (int j = 0; j < result.GetLength(1); j++)
                {
                    result[i, j] *= scalar;
                }
            }
            return result;
        }
 
        public static Matrix operator *(Matrix matrix, double scalar)
        {
            return scalar * matrix;
        }
 
        public static Matrix operator +(Matrix one, Matrix another)
        {
            return GetMatrix(one, another, 1);
        }
 
        public static Matrix operator -(Matrix one, Matrix another)
        {
            return GetMatrix(one, another, -1);
        }
 
        private static Matrix GetMatrix(Matrix one, Matrix another, int sign)
        {
            var m = GetDim(one, another, 0);
            int n = GetDim(one, another, 1);
            var res = new double[m, n];
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    res[i, j] = one[i, j] + another[i, j] * sign;
                }
            }
            return new Matrix(res);
        }
 
        private static int GetDim(Matrix one, Matrix another, int dim)
        {
            int dimOne = one._value.GetLength(dim);
            int dimAnother = another._value.GetLength(dim);
 
            if (dimOne != dimAnother)
            {
 
                throw new ArgumentException(DimentionExceptionMessage);
            }
            return dimOne;
        }
 
        private int GetDimIfSquare()
        {
            int x = _value.GetLength(0);
            int y = _value.GetLength(1);
            if (x != y)
            {
                throw new ArgumentException(DimentionExceptionMessage);
            }
            return x;
        }
 
        public static Matrix operator /(Matrix matrix, double scalar)
        {
            return matrix * (1.0 / scalar);
        }
 
        public double this[int i, int j]
        {
            get { return _value[i, j]; }
            set { _value[i, j] = value; }
        }
 
        public IEnumerator<double> GetEnumerator()
        {
            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (double d in _value)
            {
                yield return d;
            }
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        public static implicit operator Matrix(double[,] doubles)
        {
            return new Matrix(doubles);
        }
 
        public static explicit operator double[,](Matrix matrix)
        {
            return matrix._value;
        }
 
        private static double[,] Multiply(double[,] a, double[,] b)
        {
            if (a.GetLength(1) != b.GetLength(0))
                throw new ArgumentException(DimentionExceptionMessage);
            return SafeMultiply(a, b);
        }
 
        private static double[,] SafeMultiply(double[,] a, double[,] b)
        {
            const int blocksize = 8;
            var imax = a.GetLength(0);
            int jmax = b.GetLength(1);
            int kmax = a.GetLength(1);
 
            var result = new double[imax, jmax];
            int completedTasks = 0, totalTasks = (int) Math.Ceiling(imax/(double) blocksize);
            var reset = new ManualResetEvent(false);
            for (int i0 = 0; i0 < imax; i0 += blocksize)
            {
                int ilocal = i0;
                ThreadPool.QueueUserWorkItem(state =>
                {
                    for (int j0 = 0; j0 < jmax; j0 += blocksize)
                        for (int k0 = 0; k0 < kmax; k0 += blocksize)
                            for (int i = ilocal; i < Math.Min(imax, ilocal + blocksize); i++)
                                for (int j = j0; j < Math.Min(jmax, j0 + blocksize); j++)
                                    for (int k = k0; k < Math.Min(kmax, k0 + blocksize); k++)
                                    {
                                        result[i, j] += a[i, k]*b[k, j];
                                    }
                    if (Interlocked.Increment(ref completedTasks) == totalTasks)
                    {
                        reset.Set();
                    }
                });
            }
            reset.WaitOne();
            return result;
        }
 
 
        public int GetLength(int dim)
        {
            return _value.GetLength(dim);
        }
 
        public Matrix Pow(int power)
        {
            int dim = GetDimIfSquare();
            var result = GetE(dim)._value;
            var tmp = _value;
            while (power != 0)
            {
                if (power % 2 != 0)
                {
                    result = SafeMultiply(tmp, result);
                    power -= 1;
                }
                tmp = SafeMultiply(tmp, tmp);
                power /= 2;
            }
            return result;
        }
    }
}
Миниатюры
Возведение большой матрицы, читаемой с файла, в степень N, и запись обратно в файл на C#  
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
08.01.2015, 13:24 10
Лучший ответ Сообщение было отмечено МВлад как решение

Решение

В общем после еще тучи всяких попыток на моей машине получилось выжать 3 с небольшим секунды для возведения в 256 степень:
C#
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
 
namespace ConsoleApplication18
{
    public class Matrix : IEnumerable<double>
    {
        const string DimentionExceptionMessage = "Invalid matrix dimensions";
        public static Matrix GetE(int n)
        {
            var result = new Matrix(n, n);
            for (int i = 0; i < n; i++)
            {
                result[i, i] = 1.0;
            }
            return result;
        }
 
        private readonly double[,] _value;
 
        public Matrix(int rows, int cols)
            : this(new double[rows, cols])
        {
        }
 
        public Matrix(double[,] value)
        {
            _value = (double[,])value.Clone();
        }
 
        public static Matrix operator *(Matrix one, Matrix other)
        {
            return new Matrix(Multiply(one._value, other._value));
        }
 
        public static Matrix operator *(double scalar, Matrix matrix)
        {
            var result = (double[,])matrix._value.Clone();
            for (int i = 0; i < result.GetLength(0); i++)
            {
                for (int j = 0; j < result.GetLength(1); j++)
                {
                    result[i, j] *= scalar;
                }
            }
            return result;
        }
 
        public static Matrix operator *(Matrix matrix, double scalar)
        {
            return scalar * matrix;
        }
 
        public static Matrix operator +(Matrix one, Matrix another)
        {
            return MatrixSum(one, another, 1);
        }
 
        public static Matrix operator -(Matrix one, Matrix another)
        {
            return MatrixSum(one, another, -1);
        }
 
        private static Matrix MatrixSum(Matrix one, Matrix another, int sign)
        {
            var m = GetDim(one, another, 0);
            int n = GetDim(one, another, 1);
            var res = new double[m, n];
            for (int i = 0; i < m; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    res[i, j] = one[i, j] + another[i, j] * sign;
                }
            }
            return new Matrix(res);
        }
 
        private static int GetDim(Matrix one, Matrix another, int dim)
        {
            int dimOne = one._value.GetLength(dim);
            int dimAnother = another._value.GetLength(dim);
 
            if (dimOne != dimAnother)
                throw new ArgumentException(DimentionExceptionMessage);
            return dimOne;
        }
 
        private int GetDimIfSquare()
        {
            int x = _value.GetLength(0);
            int y = _value.GetLength(1);
            if (x != y)
                throw new ArgumentException(DimentionExceptionMessage);
            return x;
        }
 
        public static Matrix operator /(Matrix matrix, double scalar)
        {
            return matrix * (1.0 / scalar);
        }
 
        public double this[int i, int j]
        {
            get { return _value[i, j]; }
            set { _value[i, j] = value; }
        }
 
        public IEnumerator<double> GetEnumerator()
        {
            // ReSharper disable once LoopCanBeConvertedToQuery
            foreach (double d in _value)
            {
                yield return d;
            }
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        public static implicit operator Matrix(double[,] doubles)
        {
            return new Matrix(doubles);
        }
 
        public static explicit operator double[,](Matrix matrix)
        {
            return matrix._value;
        }
        public int GetLength(int dim)
        {
            return _value.GetLength(dim);
        }
 
        private static double[,] Multiply(double[,] a, double[,] b)
        {
            if (a.GetLength(1) != b.GetLength(0))
                throw new ArgumentException(DimentionExceptionMessage);
            return SafeMultiply(a, b, a.GetLength(0), b.GetLength(1), a.GetLength(1));
        }
 
 
        public Matrix Pow(int power)
        {
            int dim = GetDimIfSquare();
            var result = GetE(dim)._value;
            var tmp = _value;
            while (power != 0)
            {
                if (power % 2 != 0)
                {
                    result = SafeMultiply(tmp, result, dim, dim, dim);
                    power -= 1;
                }
                tmp = SafeMultiply(tmp, tmp, dim, dim, dim);
                power /= 2;
            }
            return result;
        }
 
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        static double[,] SafeMultiply(double[,] a, double[,] b, int imax, int jmax, int kmax)
        {
            double[,] c = new double[imax, jmax];
            int blockCount = Environment.ProcessorCount;
            int blockSize = (int) Math.Ceiling((double) jmax/blockCount);
            int completedBlocks = 0;
            var reset = new ManualResetEvent(false);
            for (int block = 0; block < blockCount; block++)
            {
                int from = block*blockSize;
                int to = Math.Min(from + blockSize, jmax);
                ThreadPool.QueueUserWorkItem(state =>
                {
                    var bcolj = new double[kmax];
                    for (int j = from; j < to; j++)
                    {
                        for (var k = 0; k < kmax; k++)
                            bcolj[k] = b[k, j];
 
                        for (var i = 0; i < imax; i++)
                        {
                            double s = 0;
                            for (var k = 0; k < kmax; k++)
                                s += a[i, k] * bcolj[k];
                            c[i, j] = s;
                        }
                    }
                    if (Interlocked.Increment(ref completedBlocks) == blockCount)
                    {
                        reset.Set();
                    }
                });
            }
            reset.WaitOne();
            return c;
        }
    }
}
1
21 / 4 / 2
Регистрация: 07.01.2015
Сообщений: 45
09.01.2015, 03:57  [ТС] 11
Воу! Такого ответа я совсем не ожидал! Даже не знаю, как Вас отблагодарить за такую огромную и великолепную работу, но Вы меня очень здорово выручили. Все Ваши методы работают, и работают быстро и правильно. Думаю, решения лучше этого будет очень трудно найти! Спасибо Вам огромное за Ваши старания!
0
Master of Orion
Эксперт .NET
6100 / 4956 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
09.01.2015, 04:28 12
МВлад, да не за что Заодно потренировался в оптимизациях. Была бы 15 студия, впихнул бы AVX, возведение в 1024 степень происходило бы меньше чем за секунду скорее всего. Но, что поделать, пока что майкрософт её не выпустил.

Особенно приятно, когда работу ценят, а не "шо это за хрень, а где комментарии? че-та я преподу объяснить не смог, как работает"

Добавлено через 57 секунд
МВлад, и да, с днюхой, братан!

Не по теме:

и не надо на вы обращаться, мне и 22 еще нет хД

0
21 / 4 / 2
Регистрация: 07.01.2015
Сообщений: 45
09.01.2015, 08:19  [ТС] 13
Я очень ценю Ваш труд, правда, ибо работа сделана большая и долгая, причём, я не ожидал, что мне тут помогут (я первый раз за всю жизнь обратился за помощью на форум), да ещё и полную программу сделают. Не знал, как передать это словами, подумал, что Вы не поверите и не стал это писать... :-)

Спасибо большое за поздравление. Честно говоря, Вы первый, кто меня поздравил! :-)
Ещё раз спасибо за Вашу программу! Думаю, она ещё многим поможет. :-)
0
09.01.2015, 08:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.01.2015, 08:19
Помогаю со студенческими работами здесь

Возведение матрицы в степень
Не могу понять как возвести матрицу в степень, умножая ее саму на себя. Облазил весь интернет...

Возведение матрицы в степень
Всем привет! У меня не правильно работает возведение матрицы в степень. Не могу понять, почему....

Возведение матрицы в степень
Прошу помочь, пожалуйста! Когда возвожу в 3 степень неправильно считает, я не могу увидеть, где...

Возведение матрицы в степень
Сори за то что пложу темы..Люди кто нибудь скажет как возвести на ассемблере матрицу в степень?А то...

возведение в степень матрицы
Помогите, пожалуйста, написала программу в си# возведение в степень матрицы, выводит ответ, но...

Возведение матрицы в степень
Привет. Нигде не могу найти алгоритм возведения матрицы в степень. Есть программа, которой я ввожу...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru