北 京 航 空 航 天 大 学
数值分析大作业一
学院名称:
计算机学院
专业方向:
计算机技术
学
号:
学生姓名:
教
日
师:
朱立永
期: 2018 年 11 月 12 日
1. 算法设计方案:
1. 求 1 , 501 和 s的值。
1 , 501 是矩阵的最大特征值及最小特征值。可使用幂法求出
按模最大特征值,如结果为正,即为 501 ,结果为负,则为 1 。按平
移量进行原点平移可以求得另一特征值。 s 为按模最小特征值,
|
s
|
|min
1
501
i
i
|
。可使用反幂法求得。
2. 求 A 的与数
1
k
k
501
1
40
最接近的特征值
( kki
,...,2,1
)39
。
题目可看成求以 k 为偏移量后,按模最小的特征值。即以 k 为
偏移量做位移,使用反幂法求出按模最小特征值后,加上 k ,即为所
求。
3. 求 A 的(谱范数)条件数
cond
(A
2)
和行列式det A。
det A可由 LU 分解得到。因 LU 均为三角阵,则其主对角线乘积即
为 A 的行列式。求得det A不等于 0,所以矩阵 A 为非奇异对称矩阵,
可知,
cond
)(
|
A
max
2
min
|
(1-1)
其中 max 为按模最大特征值, min 为按模最小特征值。
2. 源代码
#include
#include
#include "iostream"
#include "algorithm"
#include "iomanip"
using namespace std;
#define N 501
#define M 5
#define R 2
#define S 2
#define K 39
#define e 1.0e-12
//列
//行
//下带宽
//上带宽
//误差限
double A[M][N];
double u[N];
double t1[N], t[N];
double maximum, value1, value2, value_1, value_N, value_s, value_abs_max;
//初始矩阵
//初始向量
int max_sign, max_position;
void init_A();//初始化A
void init_u();//初始化迭代向量
void get_max();//获得绝对值最大的数值的模
void get_t();//单位化迭代向量
void get_u();//获得新迭代向量
void getValue();//获得迭代后特征值
void checkValue();//幂法第二迭代格迭代
void getMaxValue();//获取绝对值最大的特征值λ_501
void getMinValue();//获取特征值λ_1
void resolve_LU();//LU分解
void backSubstitution();//方程组回代过程
double getDetValue();//求矩阵行列式值
double getNorm();//获得迭代向量模
void get_t(double);//迭代向量单位化
void getMinABSValue();//获得绝对值最小的特征值
void inversePower();//反幂法求绝对值最小的特征值
double getCond();//求矩阵条件数
void Value_translation_min();//偏移条件下反幂法求特征值
int main() {
//初始化矩阵A
//获取绝对值最大的特征值λ_501
//获取特征值λ_1
init_A();
getMaxValue();
getMinValue();
cout << setprecision(12) << scientific << "λ1 = " << value_1 << endl;
cout << setprecision(12) << scientific << "λ501 = " << value_N << endl;
double value_det = getDetValue();
inversePower();
cout << setprecision(12) << scientific << "λs = " << value_s << endl;
double cond = getCond();
Value_translation_min();//偏移条件下反幂法求特征值
cout << setprecision(12) << scientific << "cond_A = " << cond << endl;
cout << setprecision(12) << scientific << "det = " << value_det << endl;
return 0;
//求矩阵行列式值
//反幂法求绝对值最小的特征值
//求矩阵条件数
void init_A()
{
//初始化矩阵A
for (int i = 0; i < 5; ++i) {
if (i == 0 || i == 4)
for (int j = 2; j < N; ++j)
A[i][j] = -0.064;
else if (i == 1 || i == 3)
for (int j = 1; j < N; ++j)
A[i][j] = 0.16;
else
for (int j = 0; j < N; ++j)
exp(0.1 / (j + 1));
}
}
}
}
A[i][j] = (1.64 - 0.024 * (j + 1)) * sin(0.2 * (j + 1)) - 0.64 *
void init_u()
{
//初始化迭代向量
for (int i = 0; i < N; i++)
u[i] = 1.0;
void get_max()
{
//获得绝对值最大的数值的模
max_position = 0;
maximum = fabs(u[0]);
for (int i = 1; i < N; i++) {
if (maximum < fabs(u[i])) {
max_position = i;
maximum = fabs(u[i]);
}
}
if (u[max_position] < 0)
max_sign = -1;
else max_sign = 1;
void get_t()
{
//单位化迭代向量
for (int i = 0; i < N; i++)
t1[i] = u[i] / maximum;
void get_u()
{
//获得新迭代向量
}
}
}
}
int i;
u[0] = A[2][0] * t1[0] + A[1][1] * t1[1] + A[0][2] * t1[2];
u[1] = A[3][0] * t1[0] + A[2][1] * t1[1] + A[1][2] * t1[2] + A[0][3] * t1[3];
u[N - 2] = A[4][N - 4] * t1[N - 4] + A[3][N - 3] * t1[N - 3] + A[2][N - 2] * t1[N -
u[N - 1] = A[4][N - 3] * t1[N - 3] + A[3][N - 2] * t1[N - 2] + A[2][N - 1] * t1[N -
u[i] = A[4][i - 2] * t1[i - 2] + A[3][i - 1] * t1[i - 1] + A[2][i] * t1[i] + A[1][i
2] + A[1][N - 1] * t1[N - 1];
1];
for (i = 2; i < N - 2; i++)
+ 1] * t1[i + 1] +
A[0][i + 2] * t1[i + 2];
void getValue()
{
//获得迭代后特征值
value2 = value1;
value1 = max_sign * u[max_position];
//幂法第二迭代格迭代
void checkValue()
{
init_u();
get_max();
get_t();
get_u();
getValue();
while (true) {
get_max();
get_t();
get_u();
getValue();
if (fabs((value2 - value1) / value1) < e)
break;
}
}
//获取绝对值最大的特征值λ_501
void getMaxValue()
{
checkValue();
value_abs_max = value1;
}
void getMinValue()
{
//获取特征值λ_1
double value_temp = value1;
for (int i = 0; i < N; i++) {
A[2][i] -= value_temp;
}
checkValue();
value1 += value_temp;
if (value1 < value_temp) {
value_1 = value1;
value_N = value_temp;
} else {
value_N = value1;
value_1 = value_temp;
}
}
void resolve_LU() {
double temp;
for (int k = 1; k <= N; k++) {
for (int j = k; j <= min(k + S, N); j++) {
temp = 0;
for (int t = max(max(1, k - R), j - S); t <= k - 1; t++)
temp += A[k - t + S][t - 1] * A[t - j + S][j - 1];
A[k - j + S][j - 1] = A[k - j + S][j - 1] - temp;
}
for (int i = k + 1; i <= min(k + R, N); i++) {
temp = 0;
for (int t = max(max(1, i - R), k - S); t <= k - 1; t++)
temp += A[i - t + S][t - 1] * A[t - k + S][k - 1];
A[i - k + S][k - 1] = (A[i - k + S][k - 1] - temp) / A[S][k - 1];
}
}
}
void backSubstitution()//方程组回代过程
{
double temp = 0;
for (int i = 2; i < N + 1; i++) {
for (int t = max(1, i - R); t < i; t++)
t1[i - 1] -= A[i - t + S][t - 1] * t1[t - 1];
}
u[N - 1] = t1[N - 1] / A[S][N - 1];
for (int i = N - 1; i > 0; i--) {
temp = 0;
for (int t = i + 1; t <= min(i + S, N); t++)
temp += A[i - t + S][t - 1] * u[t - 1];
u[i - 1] = (t1[i - 1] - temp) / A[S][i - 1];
double getDetValue()
{
//求矩阵行列式值
double det = 1;
init_A();
resolve_LU();
for (int i = 0; i < N; i++)
det = det * A[2][i];
return det;
}
}
}
}
double getNorm()
{
//获得迭代向量模
double normal = 0;
for (int i = 0; i < N; i++)
normal += u[i] * u[i];
normal = sqrt(normal);
return normal;
void get_t(double normal)
{
//迭代向量单位化
for (int i = 0; i < N; i++) {
t1[i] = u[i] / normal;
t[i] = t1[i];
}
}
void getMinABSValue()
{
value2 = value1;
value1 = 0;
for (int i = 0; i < N; i++)
value1 += t[i] * u[i];
value1 = 1 / value1;
//获得绝对值最小的特征值
}
}
}
//反幂法求绝对值最小的特征值
void inversePower()
{
double norm = 0;
int count = 0;
value1 = 0, value2 = 0;
init_u();
norm = getNorm();
get_t(norm);
backSubstitution();
getMinABSValue();
while (count < 10000) {
count++;
norm = getNorm();
get_t(norm);
backSubstitution();
getMinABSValue();
if (fabs((value2 - value1) / value1) < e)
break;
}
value_s = value1;
double getCond()
{
//求矩阵条件数
return fabs(value_abs_max / value_s);