fork(1) download
  1. #include <stdio.h>
  2. #include <math.h>
  3.  
  4. #define EPSILON 1e-7 // 変化量の判定基準
  5. #define MAX_ITER 100
  6.  
  7. // 確定した特性方程式 f(λ)
  8. double f(double lambda) {
  9. return pow(lambda, 4) + pow(lambda, 3) - 54.0 * pow(lambda, 2) - 224.0 * lambda - 345.0;
  10. }
  11.  
  12. // 導関数 f'(λ)
  13. double df(double lambda) {
  14. return 4.0 * pow(lambda, 3) + 3.0 * pow(lambda, 2) - 108.0 * lambda - 224.0;
  15. }
  16.  
  17. void solve_newton(int attempt, double lambda0) {
  18. double lambda = lambda0;
  19. int iter = 0;
  20.  
  21. while (iter <= MAX_ITER) {
  22. double f_val = f(lambda);
  23. double df_val = df(lambda);
  24.  
  25. if (fabs(df_val) < 1e-12) {
  26. printf("試行 #%d (初期値 %5.1f) -> 傾きが平らなため失敗\n", attempt, lambda0);
  27. return;
  28. }
  29.  
  30. // 次の修正値を計算
  31. double delta = f_val / df_val;
  32. lambda -= delta;
  33. iter++;
  34.  
  35. // 【修正】yの値ではなく、「x(lambda)の移動距離」が基準値以下になったら収束とみなす
  36. if (fabs(delta) < EPSILON) {
  37. printf("試行 #%d (初期値 %5.1f) -> 収束成功 (%2d回) | 固有値解 λ = %.10f\n",
  38. attempt, lambda0, iter, lambda);
  39. return;
  40. }
  41. }
  42. printf("試行 #%d (初期値 %5.1f) -> 未収束\n", attempt, lambda0);
  43. }
  44.  
  45. int main() {
  46. // 判定条件を移動距離に変えたため、この素直な初期値で4つの解が綺麗に分かれます
  47. double initial_lambda[] = {10.0, 3.0, 1.0, -5.0};
  48.  
  49. printf("=== ニュートン・ラフソン法による実数解(固有値)の探索結果 ===\n");
  50. for (int i = 0; i < 4; i++) {
  51. solve_newton(i + 1, initial_lambda[i]);
  52. }
  53.  
  54. return 0;
  55. }
Success #stdin #stdout 0s 5312KB
stdin
Standard input is empty
stdout
=== ニュートン・ラフソン法による実数解(固有値)の探索結果 ===
試行 #1 (初期値  10.0) -> 収束成功 ( 5回) | 固有値解 λ = 8.6962148612
試行 #2 (初期値   3.0) -> 収束成功 (10回) | 固有値解 λ = -5.4892537611
試行 #3 (初期値   1.0) -> 収束成功 (15回) | 固有値解 λ = -5.4892537611
試行 #4 (初期値  -5.0) -> 収束成功 ( 5回) | 固有値解 λ = -5.4892537611