老师让我们课余时间利用所学编写一个程序计算1600阶行列式的值,我一开始使用归纳法的思想去想的,先编出一个二阶行列式的代码,再编一个三阶行列式,二者一组合,得到他们的共有部分,但是我发现for 结构太多了,没法进行合并,我把一开始的代码先粘上给大家一些思考。
# include <iostream>
using namespace std;
int arrange(int arr[], int len);
int main(void)
{
int time = 1;
int sum = 0;
int i, m, n;
int sign = 1;
int arr[3][3] =
{
{1,2,3},
{4,5,6},
{7,8,9}
};
for (m = 0; m < 3; m++)
{
for (n = 0; n < 3; n++)
{
if (n != m)
{
for (i = 0; i < 3; i++)
{
if (i != n && i != m)
{
time *= arr[0][m];
time *= arr[1][n];
time *= arr[2][i];
int array[] = { m,n,i };
int len = sizeof(array) / sizeof(array[0]);
sign = arrange(array, len);
sum += sign * time;
time = 1;
}
}
}
}
}
cout << "sum = " << sum << endl;
return 0;
}
int arrange(int arr[], int len)
{
int i, j, temp;
int count = 0;
for (i = 0; i < len - 1; i++)
{
for (j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
count++;
}
}
}
if (count % 2)
return -1;
else
return 1;
}
不过我现在又有一种启发,因为我在引入一个新的for 循环操控行列不断的重复以概括全部情况,但是每加一个 for 这种操控是有负效应的,因此我现在又有了一种想法,我们可以利用goto 函数重新调用函数,防止产生多个 for 为后期的合并造成了很大的困扰。
用 goto 函数调用for 循环,我在上面的那个程序就不体现了,不过接下来的这个程序体现了goto 函数 。
接下来的这个程序是利用的行列式计算的性质,把行列式化为上三角,利用对角线来计算,这种方法感觉挺难的,但是付诸于实现其实是很简单的。我们可以理清一下思路:无非就是,user 输入行列式,系统把对角线之下的数据均变为0。
好了,废话少说,我们直接上代码
# include <iostream>
using namespace std;
# define N 4
int time = 1;
//user输入计算的值
void SCANF(int arr[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cout << "请输入 arr[" << i << "][" << j << "] 的值 : ";
cin >> arr[i][j];
}
}
}
//向user展示他输入的N阶行列式的效果
void PRINTF(int arr[N][N])
{
cout << "您的" << N << "阶行列式为" << endl;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
cout << "\t" << arr[i][j];
}
cout << endl;
}
}
//化成上三角并进行计算
//在16:33发现了一个不严谨的地方,就是一开始如果arr[0][0] = 0 怎么办?
void TRANSFORM(int arr[N][N])
{
cout << "化成上三角后为:" << endl;
int n = 0;
int count = 0;
k:
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (i > n)
{
double m = 1.0 * arr[i][n] / arr[n][n];
for (int t = 0; t < N; t++)
{
arr[i][t] += arr[n][t] * (-1) * m;
}
}
}
count++;
cout << "count = " << count << endl;
}
if (count < (N-1) * N)
{
n++;
goto k;
}
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
{
if (row == col)
time *= arr[row][col];
}
}
}
int main(void)
{
int arr[N][N];
SCANF(arr);
PRINTF(arr);
TRANSFORM(arr);
PRINTF(arr);
cout << N << "阶行列式的值为: " << time << endl;
return 0;
}
可以看到利用了模块化实际的思想,把这个程序的三大主干均分开了,很明显,这个程序难度最大的地方就是第三个函数(void TRANSFORM(int arr[N][N]))
void TRANSFORM(int arr[N][N])
{
cout << "化成上三角后为:" << endl;
int n = 0;
int count = 0;
k:
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (i > n)
{
double m = 1.0 * arr[i][n] / arr[n][n];
for (int t = 0; t < N; t++)
{
arr[i][t] += arr[n][t] * (-1) * m;
}
}
}
count++;
cout << "count = " << count << endl;
}
if (count < (N-1) * N)
{
n++;
goto k;
}
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
{
if (row == col)
time *= arr[row][col];
}
}
}
首先我先澄清一下,老师说的1600阶行列式的元素仅有0、1组成,这在这个程序中运行当然已经绰绰有余了。
如果想真的当个平时作业用的计算器,这个程序还有很大的不足,最大的不足是误差,因为我们不能保证在未经处理的编译器中 3 *(7/3)的结果为7,所以未来保证上三角真的成功出现,被迫把数组定义成了int 类型,防止小数的出现,还有一个不足我在程序中已经表明,这个程序无法运行对角线含0 元素的行列式。
之后,我还会对这个程序进行改进,对此文进行加以修改。
小靴子编写代码到时候超级不容易才有了此程序,大家留下个赞呗~(跪求)(跪求)(跪求)