fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4.  
  5. #define SIZE 4
  6. #define EPSILON 1e-9 // 収束判定条件
  7. #define MAX_ITER 1000 // 最大反復回数
  8.  
  9. // 行列とベクトルの積 y = A * x
  10. void mat_vec_mul(double A[SIZE][SIZE], double *x, double *y, int n) {
  11. for (int i = 0; i < n; i++) {
  12. y[i] = 0.0;
  13. for (int j = 0; j < n; j++) {
  14. y[i] += A[i][j] * x[j];
  15. }
  16. }
  17. }
  18.  
  19. int main() {
  20. // 自身で設定した行列A
  21. double A[SIZE][SIZE] = {
  22. {1.0, 2.0, 3.0, 5.0},
  23. {3.0, -5.0, 1.0, 4.0},
  24. {5.0, 9.0, 2.0, -6.0},
  25. {1.0, 7.0, 4.0, 1.0}
  26. };
  27.  
  28. double x[SIZE], y[SIZE];
  29. double lambda_old = 0.0, lambda_new = 0.0;
  30.  
  31. // 1. 初期値の設定 [1, 1, 1, 1]^T
  32. for (int i = 0; i < SIZE; i++) {
  33. x[i] = 1.0;
  34. }
  35.  
  36. printf("=== スライドに準拠したべき乗法(第1成分を1に正規化) ===\n");
  37. printf("初期ベクトル x(0): [%.1f, %.1f, %.1f, %.1f]\n\n", x[0], x[1], x[2], x[3]);
  38. printf("%-5s | %-12s | %-12s | %-30s\n", "Iter", "固有値の近似", "差分値", "固有ベクトルx(k)");
  39. printf("----------------------------------------------------------------------------\n");
  40.  
  41. int actual_iters = 0;
  42. for (int iter = 1; iter <= MAX_ITER; iter++) {
  43. actual_iters = iter;
  44.  
  45. // y = A * x
  46. mat_vec_mul(A, x, y, SIZE);
  47.  
  48. // 【スライド準拠】1行目の成分を固有値の推定値(係数)として抽出
  49. lambda_new = y[0];
  50.  
  51. // 【スライド準拠】第1成分が1になるように全体を割る (くくり出す)
  52. if (fabs(lambda_new) < 1e-12) break;
  53. for (int i = 0; i < SIZE; i++) {
  54. y[i] /= lambda_new;
  55. }
  56.  
  57. // 収束判定 (固有値の変化量を追跡)
  58. double diff = fabs(lambda_new - lambda_old);
  59.  
  60. // 収束状況の出力表示 (スライドのように推移がわかる工夫)
  61. if (iter <= 5 || iter % 5 == 0) {
  62. printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n",
  63. iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
  64. }
  65.  
  66. if (diff < EPSILON) {
  67. if (iter % 5 != 0 && iter > 5) {
  68. printf("%-5d | %-12.8f | %-12.4e | [%.5f, %.5f, %.5f, %.5f]\n",
  69. iter, lambda_new, diff, y[0], y[1], y[2], y[3]);
  70. }
  71. break;
  72. }
  73.  
  74. // 次のステップに向けて x を更新
  75. for (int i = 0; i < SIZE; i++) {
  76. x[i] = y[i];
  77. }
  78. lambda_old = lambda_new;
  79. }
  80.  
  81. printf("----------------------------------------------------------------------------\n");
  82. printf("反復回数 %d 回で収束しました。\n", actual_iters);
  83.  
  84. // === 計算結果の表示 ===
  85. printf("\n=== 計算結果 ===\n");
  86. printf("最大固有値 (λ1) : %.10f\n", lambda_new);
  87. printf("対応する固有ベクトル (x1) : [");
  88. for (int i = 0; i < SIZE; i++) {
  89. printf("%.10f%s", y[i], (i == SIZE - 1) ? "]\n" : ", ");
  90. }
  91.  
  92. return 0;
  93. }
Success #stdin #stdout 0.01s 5288KB
stdin
Standard input is empty
stdout
=== スライドに準拠したべき乗法(第1成分を1に正規化) ===
初期ベクトル x(0): [1.0, 1.0, 1.0, 1.0]

Iter  | 固有値の近似 | 差分値    | 固有ベクトルx(k)        
----------------------------------------------------------------------------
1     | 11.00000000  | 1.1000e+01   | [1.00000, 0.27273, 0.90909, 1.18182]
2     | 10.18181818  | 8.1818e-01   | [1.00000, 0.71429, 0.21429, 0.75893]
3     | 6.86607143   | 3.3157e+00   | [1.00000, 0.39012, 1.06372, 1.10923]
4     | 10.51755527  | 3.6515e+00   | [1.00000, 0.62277, 0.37871, 0.86474]
5     | 7.70536597   | 2.8122e+00   | [1.00000, 0.48327, 0.80125, 1.00436]
10    | 8.79815357   | 2.6057e-01   | [1.00000, 0.54686, 0.60936, 0.94216]
15    | 8.68606056   | 2.6271e-02   | [1.00000, 0.54085, 0.62706, 0.94795]
20    | 8.69723317   | 2.6313e-03   | [1.00000, 0.54145, 0.62528, 0.94737]
25    | 8.69611282   | 2.6369e-04   | [1.00000, 0.54139, 0.62545, 0.94743]
30    | 8.69622509   | 2.6425e-05   | [1.00000, 0.54140, 0.62544, 0.94742]
35    | 8.69621384   | 2.6481e-06   | [1.00000, 0.54140, 0.62544, 0.94742]
40    | 8.69621496   | 2.6536e-07   | [1.00000, 0.54140, 0.62544, 0.94742]
45    | 8.69621485   | 2.6592e-08   | [1.00000, 0.54140, 0.62544, 0.94742]
50    | 8.69621486   | 2.6649e-09   | [1.00000, 0.54140, 0.62544, 0.94742]
53    | 8.69621486   | 6.7023e-10   | [1.00000, 0.54140, 0.62544, 0.94742]
----------------------------------------------------------------------------
反復回数 53 回で収束しました。

=== 計算結果 ===
最大固有値 (λ1)          : 8.6962148610
対応する固有ベクトル (x1) : [1.0000000000, 0.5413991519, 0.6254386680, 0.9474201107]