Оператор матричного класса C++* возвращает неверный ответC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Оператор матричного класса C++* возвращает неверный ответ

Сообщение Anonymous »

Мне было поручено написать довольно простой код, который реализует матричный класс с типичным набором матричных операций, например умножением матриц с записями, взятыми по модулю 1000. Я придумал следующее решение:

Код: Выделить всё

matrix operator*(const matrix &A, const matrix &B)
{
if (A.m1 != B.n1)
throw runtime_error("MULTIPLY");

matrix C(A.n1, B.m1);
matrix Bt(B.m1, B.n1);
for (int i = 0; i < B.n1; ++i)
for (int j = 0; j < B.m1; ++j)
Bt.tab[j][i] = B.tab[i][j];

for (int i = 0; i < A.n1; ++i)
{
int *rowA = A.tab[i];
int *rowC = C.tab[i];

for (int j = 0; j < B.m1; ++j)
{
const int *rowB = Bt.tab[j];
long long sum = 0;
for (int k = 0; k < A.m1; ++k)
sum += (long long)rowA[k] * rowB[k];
rowC[j] = sum%1000;
}
}
return C;
}
Система оценок моего университета выдает ошибку неправильного ответа в определенном тестовом примере, который проверяет именно указанный выше оператор. Тестовый пример скрыт, но с помощью простого обратного проектирования я смог определить, что это происходит для некоторых довольно больших матриц (сумма измерений +/- 2000). Некоторые примечания:
  • Я проверил, что проблем с обработкой ошибок нет.
  • Использование Bt необходимо в целях оптимизации.
  • Нет проблем с получением суммы %1000. Во-первых, он не будет возвращать отрицательные значения, поскольку предполагается, что записи неотрицательные, во-вторых, я подсчитал, что вероятность переполнения отсутствует.
Вот некоторые другие соответствующие блоки кода:

Код: Выделить всё

class matrix
{
int n1, m1;
int **tab;

public:
matrix(int rows=0, int cols=0);
matrix(const matrix &A);
~matrix();
void operator=(const matrix &A);
long long determinant();
friend matrix operator+(const matrix &A, const matrix &B);
friend matrix operator*(const matrix &A, const matrix &B);
friend matrix operator^(const matrix &A, int k);
friend ostream& operator(istream &is, matrix &A);
};

Код: Выделить всё

matrix::matrix(int rows, int cols) : n1(rows), m1(cols)
{
if (n1 == 0 || m1 == 0)
{
tab = nullptr;
return;
}
tab = new int*[n1];
for (int i = 0; i < n1; i++)
{
tab[i] = new int[m1]();
}
}

Код: Выделить всё

oid op_multiply() {
int n1, m1;
cin >> n1 >> m1;
matrix A(n1,m1);
cin >> A;
int n2, m2;
cin >> n2 >> m2;
matrix B(n2,m2);
cin >> B;
try
{
cout > op;
ops[op]();
}
return 0;
}
Буду очень благодарен, если укажете здесь на ошибку. Я застрял в отладке этого оператора в течение 5 часов и не понимаю, в чем дело.
РЕДАКТИРОВАТЬ: Моя попытка MRE:

Код: Выделить всё

#include 
#include 
#include 
#include 
using namespace std;

class matrix
{
int n1, m1;
int **tab;

public:
matrix(int rows=0, int cols=0);
matrix(const matrix &A);
~matrix();
friend matrix operator*(const matrix &A, const matrix &B);
friend ostream& operator(istream &is, matrix &A);
};

matrix::matrix(int rows, int cols) : n1(rows), m1(cols)
{
if (n1 == 0 || m1 == 0)
{
tab = nullptr;
return;
}
tab = new int*[n1];
for (int i = 0; i < n1; i++)
{
tab[i] = new int[m1]();
}
}

matrix::matrix(const matrix &A) : n1(A.n1), m1(A.m1)
{
if (n1 == 0 || m1 == 0)
{
tab = nullptr;
return;
}
tab = new int*[n1];
for (int i = 0; i < n1; i++)
{
tab[i] = new int[m1];
for (int j = 0; j < m1; j++)
tab[i][j] = A.tab[i][j];
}
}

matrix::~matrix()
{
if (!tab) return;
for (int i = 0; i < n1; i++)
delete[] tab[i];
delete[] tab;
}

matrix operator*(const matrix &A, const matrix &B)
{
if (A.m1 != B.n1)
throw runtime_error("MULTIPLY");

matrix C(A.n1, B.m1);

matrix Bt(B.m1, B.n1);
for (int i = 0; i < B.n1; ++i)
for (int j = 0; j < B.m1; ++j)
Bt.tab[j][i] = B.tab[i][j];

for (int i = 0; i < A.n1; ++i)
{
int *rowA = A.tab[i];
int *rowC = C.tab[i];

for (int j = 0; j < B.m1; ++j)
{
const int *rowB = Bt.tab[j];
long long sum = 0;
for (int k = 0; k < A.m1; ++k)
sum += (long long)rowA[k] * rowB[k];
rowC[j] = sum%1000;
if (rowC[j] < 0)
rowC[j] = -rowC[j];
}
}
return C;
}

ostream& operator> n1 >> m1;
matrix A(n1,m1);
cin >> A;

int n2, m2;
cin >> n2 >> m2;
matrix B(n2,m2);
cin >> B;

try
{
cout  z;
void (*ops[2])() = {nullptr, op_multiply};

while (z--)
{
int op; cin >> op;
ops[op]();
}
return 0;
}
EDIT 2: Пример ввода
1
1
10 10
473 580 48 275 937 929 618 565 995 902
490 933 593 958 267 892 811 47 756 135
279 576 854 580 466 341 738 664 69 335
663 568 114 910 563 185 630 878 171 443
110 100 768 855 634 636 647 369 694 462
832 170 568 150 142 653 321 50 917 817
925 504 618 465 568 56 627 773 465 926
178 570 157 868 183 142 525 562 455 751
727 412 980 716 498 439 743 975 809 482
507 195 790 227 130 346 327 443 842 905
10 10
424 221 977 925 854 350 155 382 721 462
640 229 685 157 895 108 319 471 274 446
15 875 20 18 16 280 248 947 48 115
56 157 65 443 718 718 221 507 447 897
636 774 816 402 573 704 263 183 913 268
723 334 106 67 452 8 802 601 956 943
390 784 97 599 409 479 647 681 717 456
407 215 157 176 62 56 3 976 12 513
249 621 388 23 484 15 711 930 209 132
360 652 880 686 821 544 935 851 471 16

Подробнее здесь: https://stackoverflow.com/questions/798 ... ong-answer
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»