fork download
  1. #include <stdio.h>
  2. #include <math.h>
  3.  
  4. #define EPSILON 1e-7 // べき乗法と合わせた収束判定条件
  5. #define MAX_ITER 100
  6.  
  7. // 1つ目の行列の特性方程式 f(λ)
  8. double f(double lambda) {
  9. return pow(lambda, 4) + pow(lambda, 3) - 88.0 * pow(lambda, 2) - 132.0 * lambda + 603.0;
  10. }
  11.  
  12. // 導関数 f'(λ)
  13. double df(double lambda) {
  14. return 4.0 * pow(lambda, 3) + 3.0 * pow(lambda, 2) - 176.0 * lambda - 132.0;
  15. }
  16.  
  17. void solve_newton(int attempt, double lambda0) {
  18. double lambda = lambda0;
  19. int iter = 0;
  20.  
  21. printf("\n--- 試行 #%d: (初期値 lambda0 = %.2f) ---\n", attempt, lambda0);
  22. printf("%-5s %-15s\n", "反復", "lambda");
  23. printf("-------------------------\n");
  24.  
  25. while (iter <= MAX_ITER) {
  26. double f_val = f(lambda);
  27. double df_val = df(lambda);
  28.  
  29. // lambda の値のみを綺麗に出力
  30. printf("%-5d %-15.10f\n", iter, lambda);
  31.  
  32. // 収束判定
  33. if (fabs(f_val) < EPSILON) {
  34. printf(">> 収束しました(反復回数: %d回)\n", iter);
  35. printf(">> 得られた固有値 (lambda): %.10f\n", lambda);
  36. return;
  37. }
  38.  
  39. // 導関数がゼロに近すぎる場合の安全対策
  40. if (fabs(df_val) < 1e-12) {
  41. printf(">> 失敗: 導関数が0に近づきすぎました。\n");
  42. return;
  43. }
  44.  
  45. // ニュートン・ラフソン法の更新式: λ = λ - f(λ)/f'(λ)
  46. lambda -= f_val / df_val;
  47. iter++;
  48. }
  49. printf(">> 失敗: %d回以内に収束しませんでした。\n", MAX_ITER);
  50. }
  51.  
  52. int main() {
  53. // すべての実数解(固有値)を見つけられるように複数の初期値を設定
  54. // 8.0 からスタートすると、べき乗法で求めた最大固有値に収束します
  55. double initial_lambda[] = {8.0, 5.0, -1.0, -9.0};
  56.  
  57. for (int i = 0; i < 4; i++) {
  58. solve_newton(i + 1, initial_lambda[i]);
  59. }
  60.  
  61. return 0;
  62. }
Success #stdin #stdout 0s 5320KB
stdin
Standard input is empty
stdout
--- 試行 #1: (初期値 lambda0 = 8.00) ---
反復 lambda         
-------------------------
0     8.0000000000   
1     10.1100000000  
2     9.4161772498   
3     9.2764110802   
4     9.2710036396   
5     9.2709957115   
>> 収束しました(反復回数: 5回)
>> 得られた固有値 (lambda): 9.2709957115

--- 試行 #2: (初期値 lambda0 = 5.00) ---
反復 lambda         
-------------------------
0     5.0000000000   
1     1.5514874142   
2     2.0631235210   
3     2.0251032775   
4     2.0249184719   
5     2.0249184675   
>> 収束しました(反復回数: 5回)
>> 得られた固有値 (lambda): 2.0249184675

--- 試行 #3: (初期値 lambda0 = -1.00) ---
反復 lambda         
-------------------------
0     -1.0000000000  
1     -16.0465116279 
2     -12.8135114486 
3     -10.6237788701 
4     -9.2955161988  
5     -8.6821271781  
6     -8.5382465620  
7     -8.5305809921  
8     -8.5305597600  
9     -8.5305597598  
>> 収束しました(反復回数: 9回)
>> 得られた固有値 (lambda): -8.5305597598

--- 試行 #4: (初期値 lambda0 = -9.00) ---
反復 lambda         
-------------------------
0     -9.0000000000  
1     -8.5945945946  
2     -8.5319917371  
3     -8.5305604990  
4     -8.5305597598  
>> 収束しました(反復回数: 4回)
>> 得られた固有値 (lambda): -8.5305597598