ошибка вывода «gsl: деление на две части.c:55: ОШИБКА: значение функции не является конечным» не совпадает со строкой 55 в файле bisection.c

#c #gsl

Вопрос:

Я хочу использовать процедуру деления GSL на две части для поиска корней функции f(x)=1/(2sin(x)^2) log(sin(x))-k, константа k, на интервале [0;Pi/2].

      int main(void *params){
  
     struct func_params *part= (struct func_params*)params;
    
     int status;
     int iter = 0, max_iter = 10;
     const gsl_root_fsolver_type *R;
     gsl_root_fsolver *s;
     double x_lo = 1e-4, x_hi = M_PI/2.;

     gsl_function F;
     F.function = amp;my_func;
     F.params = amp;params;
     R = gsl_root_fsolver_bisection;
     s = gsl_root_fsolver_alloc(R);
     gsl_root_fsolver_set(s,amp;F,x_lo,x_hi);

     printf ("using %s methodn",gsl_root_fsolver_name(s));
     printf ("%5s [%9s, %9s] %9s s %9sn","iter", "lower", "upper", "root","err", "err(est)");

    return(0);
 

}

Этот код возвращает gsl: bisection.c:55: ERROR: function value is not finite Default GSL error handler invoked. Проблема в том, что, когда я смотрю на файл bisection.c, строка 55 не соответствует предыдущей ошибке…Есть идеи, что происходит?

Комментарии:

1. ‘log(sin(0))’ выглядит довольно необычно

2. может быть, мне следует изменить самое низкое значение. Я изменил его на 1e-4, но все та же проблема

Ответ №1:

Вы должны указать интервал таким образом, чтобы функция пересекалась y = 0 только один раз.

Например, [0.1, 2.0] здесь:

введите описание изображения здесь

 #include <stdio.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_roots.h>

double my_func(double x,  void* unused)
{
    double k = 1;
    return 1 / (2 * pow(sin(x), 2))   log(sin(x)) - k;
}

int main()
{
    gsl_function F;
    F.function = amp;my_func;
    F.params = 0;

    gsl_root_fsolver *s = gsl_root_fsolver_alloc(gsl_root_fsolver_bisection);

    double x_lo =  0.1, x_hi =  2.0;
    gsl_root_fsolver_set(s, amp;F, x_lo, x_hi);

    for(int i = 0; i < 1000; i  ) {

        int status = gsl_root_fsolver_iterate(s);

        double left_int  = gsl_root_fsolver_x_lower(s);
        double right_int = gsl_root_fsolver_x_upper(s);

        printf("iteration d: [%.04lf, %.04lf]n", i, left_int, right_int);

        status = gsl_root_test_interval(left_int, right_int, 1.0e-5, 1.0e-15);
        if(status != GSL_CONTINUE) {

            printf("status: %sn", gsl_strerror(status));
            printf("nRoot interval = [%.010lf, %.010lf]n", left_int, right_int);
            break;
        }
    }
}
 

Выход:

 $ gcc main.c -lgsl -lm amp;amp; ./a.out
iteration 000: [0.1000, 1.0500]
iteration 001: [0.5750, 1.0500]
iteration 002: [0.5750, 0.8125]
iteration 003: [0.5750, 0.6938]
iteration 004: [0.5750, 0.6344]
iteration 005: [0.5750, 0.6047]
iteration 006: [0.5898, 0.6047]
iteration 007: [0.5973, 0.6047]
iteration 008: [0.5973, 0.6010]
iteration 009: [0.5973, 0.5991]
iteration 010: [0.5982, 0.5991]
iteration 011: [0.5987, 0.5991]
iteration 012: [0.5989, 0.5991]
iteration 013: [0.5989, 0.5990]
iteration 014: [0.5989, 0.5990]
iteration 015: [0.5989, 0.5990]
iteration 016: [0.5989, 0.5990]
iteration 017: [0.5989, 0.5990]
status: success

Root interval = [0.5989471436, 0.5989543915]