Мне было поручено написать довольно простой код, который реализует матричный класс с типичным набором матричных операций, например, умножением матриц с записями, взятыми по модулю 1000 (РЕДАКТИРОВАНИЕ: размеры ограничены 1200, записи ограничены 0 и 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] = B.tab[j];
for (int i = 0; i < A.n1; ++i)
{
int *rowA = A.tab;
int *rowC = C.tab;
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]; //1200*1000*1000 < 1e18 -- no overflow
rowC[j] = sum%1000;
}
}
return C;
}
Система оценок моего университета выдает ошибку неправильного ответа в определенном тестовом примере, который проверяет именно указанный выше оператор. Тестовый пример скрыт, но с помощью простого обратного проектирования я смог определить, что это происходит для некоторых довольно больших матриц (сумма измерений +/- 2000). Некоторые примечания:
Я проверил, что проблем с обработкой ошибок нет.
Использование Bt необходимо в целях оптимизации.
Нет проблем с получением суммы %1000. Во-первых, он не будет возвращать отрицательные значения, поскольку предполагается, что записи неотрицательные, во-вторых, я подсчитал, что вероятность переполнения отсутствует.
Вот некоторые другие соответствующие блоки кода:
class matrix
{
int n1, m1;
int **tab;
Буду очень благодарен, если укажете здесь на ошибку. Я застрял в отладке этого оператора в течение 5 часов и не понимаю, в чем дело.
Моя попытка MRE:
#include
#include
#include
using namespace std;
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;
}
Мне было поручено написать довольно простой код, который реализует матричный класс с типичным набором матричных операций, например, умножением матриц с записями, взятыми по модулю 1000 (РЕДАКТИРОВАНИЕ: размеры ограничены 1200, записи ограничены 0 и 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]; //1200*1000*1000 < 1e18 -- no overflow rowC[j] = sum%1000; } } return C; }
Система оценок моего университета выдает ошибку неправильного ответа в определенном тестовом примере, который проверяет именно указанный выше оператор. Тестовый пример скрыт, но с помощью простого обратного проектирования я смог определить, что это происходит для некоторых довольно больших матриц (сумма измерений +/- 2000). Некоторые примечания: [list] [*]Я проверил, что проблем с обработкой ошибок нет. [*]Использование Bt необходимо в целях оптимизации. [*]Нет проблем с получением суммы %1000. Во-первых, он не будет возвращать отрицательные значения, поскольку предполагается, что записи неотрицательные, во-вторых, я подсчитал, что вероятность переполнения отсутствует. [/list] Вот некоторые другие соответствующие блоки кода: class matrix { int n1, m1; int **tab;
Буду очень благодарен, если укажете здесь на ошибку. Я застрял в отладке этого оператора в течение 5 часов и не понимаю, в чем дело. Моя попытка MRE: #include #include #include using namespace std;
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; }