Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90

Нужно экспертное мнение! Что рациональнее!? почему так работают функции?!

15.05.2011, 15:40. Показов 1541. Ответов 17
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет всем!
Возникли небольшие непонятки с функциями которые вычисляют интеграл по формуле симпсона.
Дело в том что ф-ция integ_2 которую я взял из книги работает во много раз быстрее чем функция integ которую я написал сам. Но на мой взгляд должно быть наоборот ибо в моей функции площадь ДОвычисляеться , а в той которую я взял из книги она просто вычисляется! помогите разобраться
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
 
#include <iostream>
#include <math.h>
 
using namespace std;
 
typedef double (*fx) (double);//указатель на функцию;
 
/*функции*/
double ff1(double x){ return fabs(x);}//exp (-x*x);
double ff2(double x){ return  x+4;}//ln (1+x*x);
double ff3(double x){ return  4-x;}//2/x*cos (x/2);
 
/*функция ищет точку пересечения функций f1 и f2*/
double FindRoot(double epsilon, fx f1, fx f2, double a, double b) 
{
   double t;
   while (fabs(b-a)>=epsilon) 
   {  t = a+((f2(b)-f1(b))*(b-a))/((f2(b)-f1(b))-(f2(a)-f1(a))); 
      if ((f2(a)-f1(a))*(f2(t)-f1(t))<0) b=t;
       else if ((f2(t)-f1(t))*(f2(b)-f1(b))<0) a=t;
       else return t;
   }
   return t;
}
 
 
/*функция считает интеграл на промижутке от а,b с точностью eps*/
double integ(double eps,fx f, double a, double b)
{
 double x,//координата по оси х
     h=(b-a)/2,//шаг
     s=f(a)+f(b),//общая сумма высот точек для вычисления интеграла
     I2,//интеграл взятый с шагом h
     I1=0,//интеграл взятый с шагом h/2
     curr_sum;//текущая сумма
 do
 {
  I2=I1;//присваиваем I2 знчение I1
  curr_sum=0;//обнуляем текущую сумму
  x=a+h/2;//начальное значение по оси х
  while(x<b)//ссумируем высоты с шагом h
  {
   curr_sum+=f(x);//прибовляем высоту точки
   x+=h;//двигаемся по [a,b] с шагном h.
  }
  h/=2;//шаг уменьшаем в два раза
  s+=2*curr_sum;//довычисляем общую сумму
  I1=(s+curr_sum+curr_sum)*(h/3);//вычисляем интеграл по формуле симпсона
 }
 while((fabs(I2-I1)/15)>eps);//проверка точности вычисления по правилу рунге
 return I1;//возвращаем значение интеграла
}
 
/*функция считает интеграл на промижутке от а,b с точностью eps*/
double integ_2 (double e,fx f, double a, double b)
{
    int n=2;//начальное число разбиений отрезка
    double s1=0,s,h; //s1 - предыдущая площадь, s - текущая площадь, h - шаг
    do 
    { 
         h = (b-a) / n; //выбираем шаг в зависимотси от n
         s = f(a)+f(b); //начяльная площадь 
         for(float i=1; i<=n/2-1; i++) 
         s+=4 * f(a + (2 * i - 1) * h) + 2 * f(a + 2 * i * h); //находим сумму точек
         s+=4 * f(b-h); //по формуле симпсона 
         s*=h/3; //по формуле симпсона 
         if(fabs(s-s1)<e) return s;//возвращаем значение площади
         s1 = s; //текущей площади предыдущую
         n*= 2; //увиличиваем число разбиений вдвое
    } 
    while(true); //бесконечный цикл
}
 
 
 
void main()
{ setlocale(LC_ALL,"Rus");
 double eps=0,roots[3],s=0;
cout<<"Введите точность (от 0 до 1): ";  cin>>eps;
 roots[0]=chord(eps,ff1,ff2,-50,50);
 roots[1]=FindRoot(eps,ff2,ff3,-50,50);
 roots[2]=FindRoot(eps,ff3,ff1,-50,50);
 for(int i=0;i<3;++i) cout<<"Точка пересечения №"<<i+1<<": "<< roots[i]<<endl;
  s=integ_2(eps,ff2,roots[0],roots[1])-integ_2(eps,ff1,roots[0],roots[1])+integ_2(eps,ff3,roots[1],roots[2])-integ_2(eps,ff1,roots[1],roots[2]);
 cout<<"\nПлощадь закрашенной фигуры (S) = "<<s<<endl;
 s=integ(eps,ff2,roots[0],roots[1])-integ(eps,ff1,roots[0],roots[1])+integ(eps,ff3,roots[1],roots[2])-integ(eps,ff1,roots[1],roots[2]);
 cout<<"\nПлощадь закрашенной фигуры (S) = "<<s<<endl;
 system("pause");
}
Добавлено через 34 минуты
помогите пожалуйста
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
15.05.2011, 15:40
Ответы с готовыми решениями:

Почему-то игнорируется эта функция, другие работают. Что не так?
void boat::atack() { srand(static_cast &lt;unsigned int&gt;(time(0))); std::cout &lt;&lt; &quot;Нажмите любую клавишу для начала боя!&quot;; ...

Нужно экспертное мнение по запросам
добрый день, друзья!.. нуждаюсь в экспертной оценке созданных запросов... заранее спасибо! Есть коллекция myresults с записями такого...

Нужно ваше экспертное мнение по этой сборке
блок питания thermaltake волга 1000w - 10400 руб корпус corsar 300r 5590 руб кулер deepcool gammaxx 300 1180 руб процессор...

17
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
15.05.2011, 16:32
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
0
Эксперт С++
 Аватар для odip
7176 / 3234 / 82
Регистрация: 17.06.2009
Сообщений: 14,164
15.05.2011, 16:32
Это скорее в раздел математика
0
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 16:38  [ТС]
Цитата Сообщение от kazak Посмотреть сообщение
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
у меня метод парабол. формула симпсона.
Довычисление это я про то что сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
15.05.2011, 16:53
Цитата Сообщение от olleg90 Посмотреть сообщение
сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
1
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:17  [ТС]
Цитата Сообщение от kazak Посмотреть сообщение
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
нет все получиться)) просто надо выбрать откуда начинать двигаться)))
у меня например в цикле начальная точка
C++
1
 x=a+h/2;//начальное значение по оси х
можете скомпилировать мою программу и убедиться что считает все правильно, но меня волнует другое. Почему моя функция работает во много раз медленнее.
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
15.05.2011, 17:36
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
0
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:44  [ТС]
Цитата Сообщение от kazak Посмотреть сообщение
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
15.05.2011, 17:51
Ладно, зайдем с другой стороны.
Покажи, как в твоей функции вычисляется это выражение
https://www.cyberforum.ru/cgi-bin/latex.cgi?2(y_2+y_4+\dots+y_{2n-2})+4(y_1+y_3+\dots+y_{2n-1})
0
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 18:51  [ТС]
это все находиться в переменной s
мы уменьшаем шаг вдвое получаться что сумма высот (нечетных ) уже вычислена. нам остается вычислить четные высоты в curr_sum.
0
Эксперт С++
1069 / 848 / 60
Регистрация: 30.04.2011
Сообщений: 1,659
15.05.2011, 20:01
Цитата Сообщение от olleg90 Посмотреть сообщение
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
А где у тебя деление на 3. Во второй функции вижу, а в твоей - нет...
Все, обнаружил.
Но вторая функция выглядит проще...
0
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 03:46  [ТС]
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Но вторая функция выглядит проще...
но ведь там в цикле стоит 6 умножений....! я все ровно не понимаю почему она работает быстрее...
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
16.05.2011, 11:36
Кажеться начал понимать ход твоей мысли, но с начальным значением промашка вышла. Попробуй такой вариант и сравни со своим.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
double integ(double eps,fx f, double a, double b)
{
   double x, // координата по оси х
             h = (b-a)/2, // шаг
             s = f(a)+f(b), // общая сумма высот точек для вычисления интеграла
             I2, // интеграл взятый с шагом h
             I1 = 0, // интеграл взятый с шагом h/2
             curr_sum; // текущая сумма
   do
   {
       I2 = I1; // присваиваем I2 знчение I1
       curr_sum = 0; // обнуляем текущую сумму
       x = a+h; // !!!!!!!!начальное значение по оси х
      while (x<b) // ссумируем высоты с шагом h
      {
          curr_sum += f(x); // прибовляем высоту точки
          x += h; // двигаемся по [a,b] с шагном h.
      }
      s += 2*curr_sum; // довычисляем общую сумму
      I1 = (s+2*curr_sum)*(h/3); // вычисляем интеграл по формуле симпсона
      h /= 2; // !!!!!!!!!шаг уменьшаем в два раза
   }while ((fabs(I2-I1)/15) > eps); // проверка точности вычисления по правилу рунге
   return I1; // возвращаем значение интеграла
}
0
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 15:57  [ТС]
не не не
если делать как Вы предлагаете то мы будем суммировать те же самые значения функций (высоты), а нам надо найти те которые лежат между уже вычисленными точками.
все ровно спасибо Вам за помощь и отзывчивость!))))
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
16.05.2011, 16:14
Да, точно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
double integ(double eps,fx f, double a, double b)
{
   double x, // координата по оси х
             h = (b-a)/2, // шаг
             s = f(a)+f(b)+2*f(a+h), // !!!!!!!!!!!!!!!!!общая сумма высот точек для вычисления интеграла
             I2, // интеграл взятый с шагом h
             I1 = 0, // интеграл взятый с шагом h/2
             curr_sum; // текущая сумма
   do
   {
       I2 = I1; // присваиваем I2 знчение I1
       curr_sum = 0; // обнуляем текущую сумму
       x = a+h/2; // начальное значение по оси х
      while (x<b) // ссумируем высоты с шагом h
      {
          curr_sum += f(x); // прибовляем высоту точки
          x += h; // двигаемся по [a,b] с шагном h.
      }
      s += 2*curr_sum; // довычисляем общую сумму
      I1 = (s+2*curr_sum)*(h/3); // вычисляем интеграл по формуле симпсона
      h /= 2; // !!!!!!!!!!!!шаг уменьшаем в два раза
   }while ((fabs(I2-I1)/15) > eps); // проверка точности вычисления по правилу рунге
   return I1; // возвращаем значение интеграла
}
1
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 16:34  [ТС]
kazak, во спасибо большое! все работает! быстрее! рациональнее!
но я все таки не пойму как начальное значение суммы влияло на скорость вычисления
да и еще там надо поменять местами 20 и 21 строчку иначе интеграл получается в два раза больше!

Добавлено через 2 минуты
ДОПИЛЕННЫЙ ДО УМА ВАРИАНТ
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
double integ(double eps,fx f, double a, double b)
{
   double x, // координата по оси х
             h = (b-a)/2, // шаг
             s = f(a)+f(b)+2*f(a+h), //общая сумма значения точек для вычисления интеграла
             I2, // интеграл взятый с шагом h
             I1 = 0, // интеграл взятый с шагом h/2
             curr_sum; // текущая сумма
   do
   {
       I2 = I1; // присваиваем I2 знчение I1
       curr_sum = 0; // обнуляем текущую сумму
       x = a+h/2; // начальное значение по оси х
      while (x<b) // суммируем значения функции с шагом h
      {
          curr_sum += f(x); // прибавляем значение функции
          x += h; // двигаемся по [a,b] с шагом h.
      }
      s += 2*curr_sum; // до вычисляем общую сумму
      h /= 2; // шаг уменьшаем в два раза
      I1 = (s+2*curr_sum)*(h/3); // вычисляем интеграл по формуле симпсона
    
   }while ((fabs(I2-I1)/15) > eps); // проверка точности вычисления по правилу рунге
   return I1; // возвращаем значение интеграла
}
0
 Аватар для kazak
3599 / 2741 / 354
Регистрация: 11.03.2009
Сообщений: 6,298
16.05.2011, 16:49
Цитата Сообщение от olleg90 Посмотреть сообщение
да и еще там надо поменять местами 20 и 21 строчку иначе интеграл получается в два раза больше!
Логично, фактически же используется интервал h/2, как-то это не учел
Цитата Сообщение от olleg90 Посмотреть сообщение
но я все таки не пойму как начальное значение суммы влияло на скорость вычисления
изначально выпадала средняя точка, число интервалов получалось нечетное число, и средний интервал был всегда в два раза больше остальных. В результате формула получалась несколько перекошенной. Думаю замедление должно было чувствоваться особенно заметно, если на средний интервал приходился локальный экстремум функции.
1
 Аватар для olleg90
40 / 40 / 12
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 17:33  [ТС]
оцените
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <cmath>
#include <time.h>
 
typedef double (*ff) (double);
 
/*функия от которой необходимо взять интеграл */
double fun ( double x)
{
return cos(x)+1;
}
 
/*функция считает интеграл на промижутке от а,b с точностью eps*/
double integ_2 (double e,ff f, double a, double b)
{
        long n=2;//начальное число разбиений отрезка
        long double s1=0,s,h; //s1 - предыдущая площадь, s - текущая площадь, h - шаг
    do 
    { 
         h = (b-a) / n; //выбираем шаг в зависимотси от n
         s = f(a)+f(b); //начяльная площадь 
         for(long double i=1; i<=n/2-1; i++) 
                 s+=4 * f(a + (2 * i - 1) * h) + 2 * f(a + 2 * i * h); //находим сумму точек
         s+=4 * f(b-h); //по формуле симпсона 
         s*=h/3; //по формуле симпсона 
         if(fabs(s-s1)<e) return s;//возвращаем значение площади
         s1 = s; //текущей площади предыдущую
         n*= 2; //увиличиваем число разбиений вдвое
    } 
    while(true); //бесконечный цикл
}
 
 
double integ(double eps,ff f, double a, double b)
{
   double x, // координата по оси х
             h = (b-a)/2, // шаг
             s = f(a)+f(b)+2*f(a+h), //общая сумма значения точек для вычисления интеграла
             I2, // интеграл взятый с шагом h
             I1 = 0, // интеграл взятый с шагом h/2
             curr_sum; // текущая сумма
   do
   {
       I2 = I1; // присваиваем I2 знчение I1
       curr_sum = 0; // обнуляем текущую сумму
       x = a+h/2; // начальное значение по оси х
      while (x<b) // суммируем значения функции с шагом h
      {
          curr_sum += f(x); // прибавляем значение функции
          x += h; // двигаемся по [a,b] с шагом h.
      }
      s += 2*curr_sum; // до вычисляем общую сумму
      h /= 2; // шаг уменьшаем в два раза
      I1 = (s+2*curr_sum)*(h/3); // вычисляем интеграл по формуле симпсона
    
   }while ((fabs(I2-I1)/15) > eps); // проверка точности вычисления по правилу рунге
   return I1; // возвращаем значение интеграла
}
 
/*главная функция*/ 
void main ()
{
setlocale(LC_ALL,"");
time_t start,end;
int time1,time2;
start = time(NULL);
std::cout<<"Решение: "<<integ(0.00001,fun,0,5000000)<<std::endl;
end = time(NULL);
time1=difftime(end, start);
std::cout<<"время работы функуии integ: "<<time1<<" сек."<<std::endl;
start = time(NULL);
std::cout<<"Решение: "<<integ_2(0.00001,fun,0,5000000)<<std::endl;
end = time(NULL);
time2=difftime(end, start);
std::cout<<"время работы функуии integ_2: "<<time2<<" сек."<<std::endl;
std::cout<<"Функция integ работает быстрее integ_2 в "<<(float)time2/time1<<" раз."<<std::endl;
system ("pause");
 
}
Добавлено через 28 секунд
у меня в 4.2 раза быстрее
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.05.2011, 17:33
Помогаю со студенческими работами здесь

Нужно экспертное мнение. Пойдет ли на старый ноутбук win7 или linux?
Всем привет! Хочу поставить на старенький ноутбук win7. Но есть сомнения в том, что он потянет его. Поэтому нужны ваши экспертные...

Экспертное мнение
Здравствуйте, сразу, напишу, что в железе я не бум-бум. Так что надеюсь на Ваше экспертное мнение. И так, что я имею на данный...

Почему функции VBA так медленно работают?
Привет всем, Еще вопрос. Я создал в VBA функцию, которая по сложной формуле считает не важно что. Если я в рабочей книге...

Первый класс подключения к базе - интересно экспертное мнение
Ну не без ютуба конечно был написан Все работает, просто мнение, или корректировки класса &lt;?php class DatabaseConnection { ...

Нужно каждый день выдавать бланк. Что рациональнее экспорт в Excel или печать отчета?
Понадобилось печатать одинаковые бланки каждый день. В созданной базе имеется запрос выдающий список номеров работников. Есть готовый...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru