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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
#1

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

15.05.2011, 15:40. Просмотров 780. Ответов 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 минуты
помогите пожалуйста
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.05.2011, 15:40
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Нужно экспертное мнение! Что рациональнее!? почему так работают функции?! (C++):

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

Перегрузка операторов - Оба случая работают правильно, почему так? - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &quot;conio.h&quot; #include &quot;windows.h&quot; using namespace::std; class Int{ private: ...

Не понимаю, что не так, почему не работает - C++
#include&lt;cstdlib&gt; #include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include &quot;iostream&quot; using namespace std; void main() {int *a,i,N; ...

Почему не правильно считает что не так? - C++
В данной программе я пытаюсь найти процентное отношение ассоциативного массива map&lt;string,int&gt;rezultat; rezultat=123421 из текстового...

Почему не собирается программа? Подскажите что не так? - C++
File.h #define _CRT_SECURE_NO_WARNINGS #include &lt;iostream&gt; #include &lt;string.h&gt; using namespace std; class File { private: ...

А почему ошибка, что функции print и read не определены в функции main()? - C++
Что-то не понимаю. Они определены в заголовочном файле. А подчеркивается красным что нет.... #include &lt;iostream&gt; #include...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
15.05.2011, 16:32 #2
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
odip
Эксперт С++
7157 / 3297 / 59
Регистрация: 17.06.2009
Сообщений: 14,164
15.05.2011, 16:32 #3
Это скорее в раздел математика
olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 16:38  [ТС] #4
Цитата Сообщение от kazak Посмотреть сообщение
Не очень понятно, как это ДОвычисление происходит. Откуда такая формула?
у меня метод парабол. формула симпсона.
Довычисление это я про то что сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
15.05.2011, 16:53 #5
Цитата Сообщение от olleg90 Посмотреть сообщение
сумма высот точек не сбрасывается и не считается заново , а к общей сумме каждый раз добавляется небольшая часть, за счет этого придется проделать меньше итераций.
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:17  [ТС] #6
Цитата Сообщение от kazak Посмотреть сообщение
Каким образом? Сумма включает в себя значения крайних точек, четверную сумму нечетных точек и двойную сумму четных точек. Если с крайними точками все просто, то с промежуточными досчитать не получится, т.к. некоторые точки при увеличении разбиения будут менять четность своей позиции.
нет все получиться)) просто надо выбрать откуда начинать двигаться)))
у меня например в цикле начальная точка
C++
1
 x=a+h/2;//начальное значение по оси х
можете скомпилировать мою программу и убедиться что считает все правильно, но меня волнует другое. Почему моя функция работает во много раз медленнее.
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
15.05.2011, 17:36 #7
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 17:44  [ТС] #8
Цитата Сообщение от kazak Посмотреть сообщение
Считает может и правильно, но твой вариант больше соответствует методу трапеций.
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
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
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
15.05.2011, 18:51  [ТС] #10
это все находиться в переменной s
мы уменьшаем шаг вдвое получаться что сумма высот (нечетных ) уже вычислена. нам остается вычислить четные высоты в curr_sum.
ValeryLaptev
Эксперт С++
1040 / 819 / 48
Регистрация: 30.04.2011
Сообщений: 1,659
15.05.2011, 20:01 #11
Цитата Сообщение от olleg90 Посмотреть сообщение
нее..... в методе трапеций1 по другому вообще) там формулы нет особой ... почти так же как и в методе прямоугольников. у меня же считается по этой формуле: тык
А где у тебя деление на 3. Во второй функции вижу, а в твоей - нет...
Все, обнаружил.
Но вторая функция выглядит проще...
olleg90
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 03:46  [ТС] #12
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Но вторая функция выглядит проще...
но ведь там в цикле стоит 6 умножений....! я все ровно не понимаю почему она работает быстрее...
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
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
34 / 34 / 6
Регистрация: 06.01.2011
Сообщений: 90
16.05.2011, 15:57  [ТС] #14
не не не
если делать как Вы предлагаете то мы будем суммировать те же самые значения функций (высоты), а нам надо найти те которые лежат между уже вычисленными точками.
все ровно спасибо Вам за помощь и отзывчивость!))))
kazak
3034 / 2355 / 155
Регистрация: 11.03.2009
Сообщений: 5,402
Завершенные тесты: 1
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; // возвращаем значение интеграла
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.05.2011, 16:14
Привет! Вот еще темы с ответами:

Почему код не работает хотя ошибок нет? Что-то не так с выделением памяти? - C++
#include &lt;math.h&gt; #include &lt;stdio.h&gt; #include &lt;conio.h&gt; #include &lt;iostream&gt; using namespace std; int n = 0; double a, b; ...

Что не так?. Чтение из файла и нужно посчитать средний балл - C++
// Лаба №5.cpp: определяет точку входа для консольного приложения. // #include &quot;stdafx.h&quot; #include &quot;math.h&quot; #include &quot;stdio.h&quot; ...

Написала программу,но работает не так, как нужно. Что исправить? - C++
Дано простое число. Написать функцию, которая находит следующее простое число. Никаких ошибок и предупреждений не выводит. Но ,допустим,...

Ошибки в функции что не так? - C++
#include &lt;iostream&gt; using namespace std; int fadd(int,int); int fmul(int,int); int fsub(int,int); int fdiv(int,int); int main()...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
16.05.2011, 16:14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru