我正在实施Strassen's matrix multiplication algorithm作为作业的一部分。我已正确编码,但我不知道为什么它会给出分段错误。 我在main中将strassen()称为 strassen(0,n,0,n); 。 n是用户给出的数,是2的幂,它是矩阵的最大尺寸(2D阵列)。 它没有给n = 4的段错误,但是对于n = 8,16,32,它给出了段错误。 代码如下所示。
void strassen(int p, int q, int r, int s)
{
int p1,p2,p3,p4,p5,p6,p7;
if(((q-p) == 2)&&((s-r) == 2))
{
p1 = ((a[p][r] + a[p+1][r+1])*(b[p][r] + b[p+1][r+1]));
p2 = ((a[p+1][r] + a[p+1][r+1])*b[p][r]);
p3 = (a[p][r]*(b[p][r+1] - b[p+1][r+1]));
p4 = (a[p+1][r+1]*(b[p+1][r] - b[p][r]));
p5 = ((a[p][r] + a[p][r+1])*b[p+1][r+1]);
p6 = ((a[p+1][r] - a[p][r])*(b[p][r] +b[p][r+1]));
p7 = ((a[p][r+1] - a[p+1][r+1])*(b[p+1][r] + b[p+1][r+1]));
c[p][r] = p1 + p4 - p5 + p7;
c[p][r+1] = p3 + p5;
c[p+1][r] = p2 + p4;
c[p+1][r+1] = p1 + p3 - p2 + p6;
}
else
{
strassen(p, q/2, r, s/2);
strassen(p, q/2, s/2, s);
strassen(q/2, q, r, s/2);
strassen(q/2, q, s/2, s);
}
}
答案 0 :(得分:2)
你的else块中的一些条件是无限递归的(至少第二个和第四个,没有检查另一个)。用笔和纸很容易证明这一点:
例如
对于`0,8,0,8,strassen(p, q/2, s/2, s)
将在每次迭代时产生:
1) 0, 4, 4, 8
2) 0, 2, 4, 8
3) 0, 1, 4, 8
4) 0, 0, 4, 8
5) 0, 0, 4, 8
...
并且因为这些结果都没有通过你的
if(((q-p) == 2)&&((s-r) == 2))
测试,该函数将运行(我怀疑分支,因为第4个函数有同样的问题......)直到堆栈结束命中,导致分段错误。
无论如何,如果你在else块中尝试做的是递归地将矩阵一分为二,那么更好的尝试将是这样的:
strassen(p, (q+p)/2, r, (r+s)/2);
strassen(p, (q+p)/2, (r+s)/2, s);
strassen((q+p)/2,q, (r+s)/2, s);
strassen((q+p)/2,q, r, (r+s)/2);
(请记住,我没有检查此代码)
答案 1 :(得分:0)
void strassen(int p, int q, int r, int s)
{
int p1,p2,p3,p4,p5,p6,p7;
if(q-p == 2 && s-r == 2)
{
p1 = (a[p][r] + a[p+1][r+1]) * (b[p][r] + b[p+1][r+1]);
p2 = (a[p+1][r] + a[p+1][r+1]) * b[p][r];
p3 = a[p][r] * (b[p][r+1] - b[p+1][r+1]);
p4 = a[p+1][r+1] * (b[p+1][r] - b[p][r]);
p5 = (a[p][r] + a[p][r+1]) * b[p+1][r+1];
p6 = (a[p+1][r] - a[p][r]) * (b[p][r] +b[p][r+1] );
p7 = (a[p][r+1] - a[p+1][r+1]) * (b[p+1][r] + b[p+1][r+1]);
c[p][r] = p1 + p4 - p5 + p7;
c[p][r+1] = p3 + p5;
c[p+1][r] = p2 + p4;
c[p+1][r+1] = p1 + p3 - p2 + p6;
}
else
{
if (q/2-p >= 2 && s/2-r >= 2) strassen(p, q/2, r, s/2);
if (q/2-p >= 2 && s-s/2 >= 2) strassen(p, q/2, s/2, s);
if (q-q/2 >= 2 && s/2-r >= 2) strassen(q/2, q, r, s/2);
if (q-q/2 >= 2 && s-s/2 >= 2) strassen(q/2, q, s/2, s);
}
}
但更简单的递归限制器将在函数的开头,如:
{
int p1,p2,p3,p4,p5,p6,p7;
if(q-p < 2 || s-r < 2) return;
if(q-p == 2 && s-r == 2)
{ ...