计算实对称矩阵特征值和特征向量

#define EPS 0.000001 #include #include int Jacobi(double matrix[][5], double vec[][5], int maxt, int n) { int it, p, q, i, j; // 函数返回值 double temp, t, cn, sn, max_element, vip, viq, aip, aiq, apj, aqj; // 临时变量 for (it = 0; it < maxt; ++it) { max_element = 0; for (p = 0; p < n-1; ++p) { for (q = p + 1; q < n; ++q) { if (fabs(matrix[p][q]) > max_element) // 记录非对角线元素最大值 max_element = fabs(matrix[p][q]); if (fabs(matrix[p][q]) > EPS) // 非对角线元素非0时才执行Jacobi变换 { // 计算Givens旋转矩阵的重要元素:cos(theta), 即cn, sin(theta), 即sn temp = (matrix[q][q] - matrix[p][p]) / matrix[p][q] / 2.0; if (temp >= 0) // t为方程 t^2 + 2*t*temp - 1 = 0的根, 取绝对值较小的根为t t = -temp + sqrt(1 + temp * temp); else t = -temp - sqrt(1 + temp * temp); cn = 1 / sqrt(1 + t * t); sn = t * cn; // Givens旋转矩阵之转置左乘matrix, 即更新matrix的p行和q行 for (j = 0; j < n; ++j) { apj = matrix[p][j]; aqj = matrix[q][j]; matrix[p][j] = cn * apj - sn * aqj; matrix[q][j] = sn * apj + cn * aqj; } // Givens旋转矩阵右乘matrix, 即更新matrix的p列和q列 for (i = 0; i < n; ++i) { aip = matrix[i][p]; aiq = matrix[i][q]; matrix[i][p] = cn * aip - sn * aiq; matrix[i][q] = sn * aip + cn * aiq; } // 更新特征向量存储矩阵vec, vec=J0×J1×J2...×Jit, 所以每次只更新vec的p, q两列 for (i = 0; i < n; ++i) { vip = vec[i][p]; viq = vec[i][q]; vec[i][p] = cn * vip - sn * viq; vec[i][q] = sn * vip + cn * viq; } } } } if (max_element <= EPS) // 非对角线元素已小于收敛标准,迭代结束 return 1; } return 0; } int main(int argc, char *argv[]) { double matrix[5][5], vec[5][5]; int i, j; for (i = 0; i < 5; ++i) { for (j = 0; j < 5; ++j) scanf("%lf", &matrix[i][j]); } Jacobi(matrix, vec, 100, 5); for (i = 0; i < 4; ++i) printf("%f ", matrix[i][i]); printf("%f/n", matrix[i][i]); return 0; }

你可能感兴趣的:(ACM)