Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 15:40     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #1
Привет всем!
Возникли небольшие непонятки с функциями которые вычисляют интеграл по формуле симпсона.
Дело в том что ф-ция 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 минуты
помогите пожалуйста
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2011, 15:40     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?!
Посмотрите здесь:

C++ Ошибки в функции что не так?
Что опять не так в функции? C++
Что не так?. Чтение из файла и нужно посчитать средний балл C++
C++ Написала программу,но работает не так, как нужно. Что исправить?
C++ Не понимаю, что не так, почему не работает
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
15.05.2011, 16:32     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #2
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
odip
Эксперт C++
 Аватар для odip
7225 / 3287 / 58
Регистрация: 17.06.2009
Сообщений: 14,165
15.05.2011, 16:32     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #3
Это скорее в раздел математика
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 16:38  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #4
Цитата Сообщение от kazak Посмотреть сообщение
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
у меня метод парабол. формула симпсона.
Довычисление это я про то что сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
15.05.2011, 16:53     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #5
Цитата Сообщение от olleg90 Посмотреть сообщение
сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:17  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #6
Цитата Сообщение от kazak Посмотреть сообщение
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
нет все получиться)) просто надо выбрать откуда начинать двигаться)))
у меня например в цикле начальная точка
C++
1
 x=a+h/2;//начальное значение по оси х
можете скомпилировать мою программу и убедиться что считает все правильно, но меня волнует другое. Почему моя функция работает во много раз медленнее.
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
15.05.2011, 17:36     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #7
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:44  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #8
Цитата Сообщение от kazak Посмотреть сообщение
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
15.05.2011, 17:51     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #9
Ладно, зайдем с другой стороны.
Покажи, как в твоей функции вычисляется это выражение
http://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})
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 18:51  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #10
это все находиться в переменной s
мы уменьшаем шаг вдвое получаться что сумма высот (нечетных ) уже вычислена. нам остается вычислить четные высоты в curr_sum.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.05.2011, 20:01     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #11
Цитата Сообщение от olleg90 Посмотреть сообщение
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
А где у тебя деление на 3. Во второй функции вижу, а в твоей - нет...
Все, обнаружил.
Но вторая функция выглядит проще...
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 03:46  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #12
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Но вторая функция выглядит проще...
но ведь там в цикле стоит 6 умножений....! я все ровно не понимаю почему она работает быстрее...
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
16.05.2011, 11:36     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #13
Кажеться начал понимать ход твоей мысли, но с начальным значением промашка вышла. Попробуй такой вариант и сравни со своим.
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; // возвращаем значение интеграла
}
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 15:57  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #14
не не не
если делать как Вы предлагаете то мы будем суммировать те же самые значения функций (высоты), а нам надо найти те которые лежат между уже вычисленными точками.
все ровно спасибо Вам за помощь и отзывчивость!))))
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
16.05.2011, 16:14     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #15
Да, точно
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; // возвращаем значение интеграла
}
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 16:34  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #16
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; // возвращаем значение интеграла
}
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
16.05.2011, 16:49     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #17
Цитата Сообщение от olleg90 Посмотреть сообщение
да и еще там надо поменять местами 20 и 21 строчку иначе интеграл получается в два раза больше!
Логично, фактически же используется интервал h/2, как-то это не учел
Цитата Сообщение от olleg90 Посмотреть сообщение
но я все таки не пойму как начальное значение суммы влияло на скорость вычисления
изначально выпадала средняя точка, число интервалов получалось нечетное число, и средний интервал был всегда в два раза больше остальных. В результате формула получалась несколько перекошенной. Думаю замедление должно было чувствоваться особенно заметно, если на средний интервал приходился локальный экстремум функции.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.05.2011, 17:33     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?!
Еще ссылки по теме:

C++ Перегрузка операторов - Оба случая работают правильно, почему так?
Почему не правильно считает что не так? C++

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

Или воспользуйтесь поиском по форуму:
olleg90
 Аватар для olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 17:33  [ТС]     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! #18
оцените
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 раза быстрее
Yandex
Объявления
16.05.2011, 17:33     Нужно экспертное мнение! Что рациональнее!? почему так работают функции?!
Ответ Создать тему
Опции темы

Текущее время: 07:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru