fork download
  1. #include <stdio.h>
  2. #include <math.h>
  3. #define N 4
  4. #define EPS 1e-6
  5. #define MAX_ITER 100
  6.  
  7. void print_matrix(double mat[N][N]) {
  8. for (int i = 0; i < N; i++) {
  9. for (int j = 0; j < N; j++) {
  10. printf("%7.4f ", mat[i][j]);
  11. }
  12. printf("\n");
  13. }
  14. }
  15.  
  16. int main() {
  17. double A[N][N] = {
  18. {5.0, 4.0, 1.0, 1.0},
  19. {4.0, 5.0, 1.0, 1.0},
  20. {1.0, 1.0, 4.0, 2.0},
  21. {1.0, 1.0, 2.0, 4.0}
  22. };
  23.  
  24. double A_orig[N][N];
  25. for (int i = 0; i < N; i++)
  26. for (int j = 0; j < N; j++)
  27. A_orig[i][j] = A[i][j];
  28.  
  29. double P[N][N] = {0};
  30. for (int i = 0; i < N; i++) P[i][i] = 1.0;
  31.  
  32. int iter = 0;
  33. printf("%-5s %-18s %-8s\n", "反復", "最大非対角成分", "要素位置");
  34. printf("---------------------------------------\n");
  35.  
  36. while (iter < MAX_ITER) {
  37. // 1. 非対角成分から絶対値が最大の要素 A[p][q] を探索
  38. int p = 0, q = 1;
  39. double max_val = fabs(A[0][1]);
  40. for (int i = 0; i < N; i++) {
  41. for (int j = i + 1; j < N; j++) {
  42. if (fabs(A[i][j]) > max_val) {
  43. max_val = fabs(A[i][j]);
  44. p = i;
  45. q = j;
  46. }
  47. }
  48. }
  49. printf("%-5d %-18.6f A[%d][%d]\n", iter, max_val, p, q);
  50.  
  51. if (max_val < EPS) {
  52. printf("---------------------------------------\n");
  53. printf("状態: 正常に収束しました。\n\n");
  54. break;
  55. }
  56.  
  57. double phi, cos_t, sin_t;
  58. if (fabs(A[p][p] - A[q][q]) < 1e-12) {
  59. phi = acos(-1.0) / 4.0;
  60. } else {
  61. phi = 0.5 * atan2(2.0 * A[p][q], A[p][p] - A[q][q]);
  62. }
  63. cos_t = cos(phi);
  64. sin_t = sin(phi);
  65.  
  66. // 行列 A の更新
  67. double Ap_old = A[p][p];
  68. double Aq_old = A[q][q];
  69. A[p][p] = Ap_old * cos_t * cos_t + Aq_old * sin_t * sin_t + 2.0 * A[p][q] * sin_t * cos_t;
  70. A[q][q] = Ap_old * sin_t * sin_t + Aq_old * cos_t * cos_t - 2.0 * A[p][q] * sin_t * cos_t;
  71. A[p][q] = A[q][p] = 0.0;
  72.  
  73. for (int i = 0; i < N; i++) {
  74. if (i != p && i != q) {
  75. double a_ip = A[i][p];
  76. double a_iq = A[i][q];
  77. A[i][p] = A[p][i] = a_ip * cos_t + a_iq * sin_t;
  78. A[i][q] = A[q][i] = -a_ip * sin_t + a_iq * cos_t;
  79. }
  80. }
  81.  
  82. for (int i = 0; i < N; i++) {
  83. double p_ip = P[i][p];
  84. double p_iq = P[i][q];
  85. P[i][p] = p_ip * cos_t + p_iq * sin_t;
  86. P[i][q] = -p_ip * sin_t + p_iq * cos_t;
  87. }
  88.  
  89. iter++;
  90. }
  91.  
  92.  
  93. printf(" 固有値 & 固有ベクトル \n");
  94. for (int j = 0; j < N; j++) {
  95. printf("Eigenvalue %d (固有値): %f\n", j + 1, A[j][j]);
  96. printf("Eigenvector %d (固有ベクトル):\n[ ", j + 1);
  97. for (int i = 0; i < N; i++) {
  98. printf("%f ", P[i][j]);
  99. }
  100. printf("]\n\n");
  101. }
  102.  
  103. printf(" 固有対の検証チェック (A*x - lambda*x) \n");
  104.  
  105. for (int j = 0; j < N; j++) {
  106. double lambda = A[j][j];
  107. printf("固有値 %d (%f) の検証:\n", j + 1, lambda);
  108.  
  109. for (int i = 0; i < N; i++) {
  110. double Ax_i = 0.0;
  111. for (int k = 0; k < N; k++) {
  112. Ax_i += A_orig[i][k] * P[k][j];
  113. }
  114. double lambda_x_i = lambda * P[i][j];
  115. double residual = fabs(Ax_i - lambda_x_i);
  116. printf(" 第 %d 行: A*x = %9.6f, lambda*x = %9.6f, 残差絶対値 = %e\n",
  117. i + 1, Ax_i, lambda_x_i, residual);
  118. }
  119. printf("\n");
  120. }
  121. return 0;
  122. }
Success #stdin #stdout 0.01s 5324KB
stdin
Standard input is empty
stdout
反復   最大非対角成分   要素位置
---------------------------------------
0       4.000000             A[0][1]
1       2.000000             A[2][3]
2       2.000000             A[0][2]
3       0.000000             A[0][3]
---------------------------------------
状態: 正常に収束しました。

     固有値 & 固有ベクトル    
Eigenvalue 1 (固有値): 10.000000
Eigenvector 1 (固有ベクトル):
[ 0.632456 0.632456 0.316228 0.316228 ]

Eigenvalue 2 (固有値): 1.000000
Eigenvector 2 (固有ベクトル):
[ -0.707107 0.707107 0.000000 0.000000 ]

Eigenvalue 3 (固有値): 5.000000
Eigenvector 3 (固有ベクトル):
[ -0.316228 -0.316228 0.632456 0.632456 ]

Eigenvalue 4 (固有値): 2.000000
Eigenvector 4 (固有ベクトル):
[ 0.000000 0.000000 -0.707107 0.707107 ]

      固有対の検証チェック (A*x - lambda*x)    
固有値 1 (10.000000) の検証:
  第 1 行: A*x =  6.324555, lambda*x =  6.324555, 残差絶対値 = 8.881784e-16
  第 2 行: A*x =  6.324555, lambda*x =  6.324555, 残差絶対値 = 1.776357e-15
  第 3 行: A*x =  3.162278, lambda*x =  3.162278, 残差絶対値 = 4.440892e-16
  第 4 行: A*x =  3.162278, lambda*x =  3.162278, 残差絶対値 = 8.881784e-16

固有値 2 (1.000000) の検証:
  第 1 行: A*x = -0.707107, lambda*x = -0.707107, 残差絶対値 = 4.440892e-16
  第 2 行: A*x =  0.707107, lambda*x =  0.707107, 残差絶対値 = 3.330669e-16
  第 3 行: A*x =  0.000000, lambda*x =  0.000000, 残差絶対値 = 1.110223e-16
  第 4 行: A*x =  0.000000, lambda*x =  0.000000, 残差絶対値 = 1.110223e-16

固有値 3 (5.000000) の検証:
  第 1 行: A*x = -1.581139, lambda*x = -1.581139, 残差絶対値 = 4.440892e-16
  第 2 行: A*x = -1.581139, lambda*x = -1.581139, 残差絶対値 = 2.220446e-16
  第 3 行: A*x =  3.162278, lambda*x =  3.162278, 残差絶対値 = 4.440892e-16
  第 4 行: A*x =  3.162278, lambda*x =  3.162278, 残差絶対値 = 0.000000e+00

固有値 4 (2.000000) の検証:
  第 1 行: A*x =  0.000000, lambda*x =  0.000000, 残差絶対値 = 1.110223e-16
  第 2 行: A*x =  0.000000, lambda*x =  0.000000, 残差絶対値 = 1.110223e-16
  第 3 行: A*x = -1.414214, lambda*x = -1.414214, 残差絶対値 = 2.220446e-16
  第 4 行: A*x =  1.414214, lambda*x =  1.414214, 残差絶対値 = 2.220446e-16