static double pfc_string_to_float_internal(const char * src) { bool neg = false; t_int64 val = 0; int div = 0; bool got_dot = false; while(*src==' ') src++; if (*src=='-') {neg = true;src++;} else if (*src=='+') src++; while(*src) { if (*src>='0' && *src<='9') { int d = *src - '0'; val = val * 10 + d; if (got_dot) div--; src++; } else if (*src=='.' || *src==',') { if (got_dot) break; got_dot = true; src++; } else if (*src=='E' || *src=='e') { src++; div += atoi(src); break; } else break; } if (neg) val = -val; return (double) val * exp_int(10, div); }
// Основная функция. На вход: EPS --- порядок погрешности // filename --- файл для вывода, local --- значения локальной погрешности в точках int runge(double *global_error, double EPS, const char*filename, double local[CHECK_POSITIONS * VAL_NUM ]) { double x,y,u,v; // x y a b double h=0; double k[K_NUM][VAL_NUM]; // числа рунге int errflag = 0; int check_time = CHECK_POSITIONS; // количество оставшихся точек на временной шкале для проверки лок погрешности int flag = 0; double h_next = 0; // механическая переменная для хранения следующего шага *global_error = 0; FILE *file = fopen(filename, "w"); if (file == NULL) errflag = -1; else{ fprintf(file, "t, x, y\n"); //вводим начальные условия x = x0; y = y0; u = u0; v = v0; h = EPS/h0; new_k(h,k,x,y,u,v); // начальные числа Рунге h = new_h(EPS,h,k,x,y,u,v); // обновляем шаг new_k(h,k,x,y,u,v); // ежели он изменился -- обновим числа Рунге for (double t = 0;t<=WORK_TIME+h;t+=h){ // если мы в нужной точке T, 3T/4, T/2, T/4, то flag == 1 if (flag == 0) if (check_time > 0) // если меньше, то точек не осталось, увы if ((nearest(t) - t <= h)&&(nearest(t) - t >= 0)){ // если мы сюда попали, то расстояние до нужной точки меньше h // объявим следующий шаг этим расстоянием h_next = nearest(t) - t; } //подсчет глобальной погрешности (*global_error) = Variation(h,k,x,y,u,v) + (*global_error) * exp_int(h,x,y); // обновляем координаты x = new_parametr(h,x,k,x,y,u,v,0); y = new_parametr(h,y,k,x,y,u,v,1); u = new_parametr(h,u,k,x,y,u,v,2); v = new_parametr(h,v,k,x,y,u,v,3); fprintf(file, "%e, %e, %e\n", t,x,y); // если мы в нужной точке T, 3T/4, T/2, T/4, то flag == 1 if (flag == 1) { local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time)] = x; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 1] = y; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 2] = u; local[CHECK_POSITIONS*(CHECK_POSITIONS - check_time) + 3] = v; h = h_next; // возвращаем исходное значение шага h_next = 0; flag = 0; check_time--; // мы же уже дошли до этой точке, осталось на одну меньше } h = new_h(EPS,h,k,x,y,u,v); //обновляем шаг if (h_next != 0){ double p; p = h; h = h_next; h_next = p;//сохраняем предыдуший шаг на случай, если новый слишком маленький flag = 1; // для того, чтобы мы видели вывод } new_k(h,k,x,y,u,v); //обновляем числа Рунге if (h<H_DEFAULT) {errflag = -2; break;} // на случай особых точек } } printf("final step = %e;\n", h); fclose(file); return errflag; }