Вопрос 5. Разработать многопоточное приложение для вычисления интеграла от заданной функции в заданных пределах.


Добавил:DMT
Дата создания:30 декабря 2007, 18:22
Дата обновления:30 декабря 2007, 18:22
Просмотров:5649 последний 25 марта, 18:17
Комментариев: 3

Вопрос 5. Разработать многопоточное приложение для вычисления интеграла от заданной функции в заданных пределах.

up

Комментарии для "Вопрос 5. Разработать многопоточное приложение для вычисления интеграла от заданной функции в заданных пределах. "


Пользователь: ruslan
Сообщений: 23
Статус: Незримый
Зарегистрирован:
5 января 2008, 2:42
Был:29 января 2008, 21:23
ruslan
smsup
Дата: 14 января 2008, 0:38 Сообщение № 1
Вариант 1 (из РГЗ по ПП).

Вычислить
image1
при 0<=a<=1.

Решение. Число из диапазона 0<=a<=1 будем вводить с помощью генератора целых чисел, полагая a = random(1000)/1000. Разработаем подпрограмму (функцию) потока. Она будет вычислять
image2
. Это вычисление производится со случайной задержкой с помощью вызова функции sleep(random(3)).

Подпрограмма имеет один параметр k, который будет передаваться в нее через LPVOID ps. Затем подпрограмма захватывает с помощью семафора внешнюю переменную s, в которой накапливается приближенное значение интеграла, прибавляет к s вычисленное значение и освобождает переменную s. Главная программа ожидает выполнения всех n потоков с помощью оператора while (j < n). Для проверки вычисленного значения приведём функцию, вычисляющую это значение с помощью одного цикла.

Код на C++
  1. #include <windows.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <dos.h>
  5. #include <iostream.h>
  6. #include <conio.h>
  7. #define n 100
  8. volatile int j=0; // для проверки в цикле while(j<n)
  9. HANDLE mut; // мьютекс
  10. double s=0; // вычисляемое значение интеграла
  11. double a; // случайное число из [0,1]
  12. //---------------------------------------------------------------------------
  13. DWORD WINAPI sum(LPVOID ps) // функция потоков
  14. {
  15. int *k = (int *)ps;
  16. double w = (double)(1./1.+(a*(*k)) /n* (a*(*k)) /n);
  17. sleep(random(3)); // задержка
  18. WaitForSingleObject(mut, INFINITE); // ждем освобождения s
  19. s = s + w; j++; // прибавляем значение
  20. ReleaseMutex(mut); // освобождаем s
  21. return 1;
  22. }
  23. //---------------------------------------------------------------------------
  24. double sum0() // простая функция
  25. {
  26. double s0=0; int k;
  27. for (k=0; k<n; k++) // циклическое вычисление интеграла
  28. s0 += (double)(1./(1.+(a*k)/n*(a*k)/n));
  29. return a/n*s0;
  30. }
  31. //---------------------------------------------------------------------------
  32. int main(int argc, char* argv[])
  33. {
  34. int i; int p[n];
  35. randomize(); a = (0.+random(1000))/1000;
  36. for(i=0; i<n; i++) p[i]=i;
  37. mut = CreateMutex(NULL,false,NULL); // создание мьютекса
  38. for(i=0; i<n; i++) // запуск потоков
  39. { // параметр - номер из [0,n-1]
  40. CreateThread(NULL,0,sum, (void *) (&p[i]),0,0);
  41. }
  42. while (j<n); // ожидание завершения всех потоков
  43. // результат вычисления с помощью потоков и простой функции
  44. cout << "\nValue obtained by threads = " << s*a/n;
  45. cout << "\nValue of the simple subprogram = " << sum0();
  46. getch();
  47. }
  48. //---------------------------------------------------------------------------
  49.  
При использовании обязательна ссылка на http://DMTSoft.ru
Пользователь: ruslan
Сообщений: 23
Статус: Незримый
Зарегистрирован:
5 января 2008, 2:42
Был:29 января 2008, 21:23
ruslan
smsup
Дата: 14 января 2008, 0:51 Сообщение № 2
Вариант 2 (мой вариант... вспоминаем выч.мат. sm ).

Вычислить интеграл по формуле Симпсона при n = 8, где n - это число интервалов.



image1



Формулу Симпсона (составную квадратичную формулу Симпсона) можно применять при четных n. В нашем случае n четно.
a = 1.2, b = 2.7, h = (b – a) / n, n = 8, m = n / 2 = 4,



image2



xi = x0 + i * h, 0<=i<=n, x0 = a.

Q1 – приближенное значение интеграла при n = 8.

Код на C++
  1. #include <windows.h>
  2. #include <conio.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. struct arg
  6. {
  7. int i;
  8. float x;
  9. };
  10. HANDLE mut_1, mut_2;
  11. float s_1=0, s_2=0;
  12. float f1 (float x) { return 1/sqrt(x*x+3.2); }
  13. //--------------------------
  14. DWORD WINAPI integral(void *data)
  15. {
  16. if((((arg*)data)->i)%2)
  17. {
  18. WaitForSingleObject(mut_1,INFINITE);
  19. s_1 += f1( ((arg*)data)->x );
  20. ReleaseMutex(mut_1);
  21. }
  22. else
  23. {
  24. WaitForSingleObject(mut_2,INFINITE);
  25. s_2 += f1( ((arg*)data)->x );
  26. ReleaseMutex(mut_2);
  27. }
  28. return 1;
  29. }
  30. //---------------------------
  31. void main(void)
  32. {
  33. float a,b,h,Q1,Q2,Q; int n,i;
  34. clrscr();
  35. printf("\n\t\t Численное интегрирование функций");
  36. puts("\n\n\t*** Формула Симпсона ***");
  37. a = 1.2; b = 2.7;
  38. n = 8; h = (b-a)/n;
  39. Q1 = Q2 = f1(a)+f1(b);
  40. float s1=0, s2=0, x=a;
  41. arg *data = new arg[n-1];
  42. HANDLE *thr = new HANDLE[n-1];
  43. mut_1 = CreateMutex(0, false,0);
  44. mut_2 = CreateMutex(0, false,0);
  45. for (i=1; i<n; i++)
  46. {
  47. x += h;
  48. if (i%2)
  49. s1 += f1(x);
  50. else
  51. s2 += f1(x);
  52. data[i-1].i = i; data[i-1].x = x;
  53. thr[i-1] = CreateThread(0,0,integral,(void*)&data[i-1],0,0);
  54. }
  55. WaitForMultipleObjects(n-1,thr,true,INFINITE);
  56. Q1 = h/3*(Q1+4*s_1+2*s_2); //в потоках
  57. Q2 = h/3*(Q2+4*s1+2*s2); //в цикле
  58. printf ("\n\t\tn= 8:");
  59. printf ("\n Приближенное значение интергала: %.7f", Q1);
  60. printf ("\n Приближенное значение интергала: %.7f", Q2);
  61. delete thr;
  62. delete data;
  63. getch();
  64. }
  65. //------
  66.  
При использовании обязательна ссылка на http://DMTSoft.ru
Пользователь: lilo
Сообщений: 38
Статус: Незримый
Зарегистрирован:
8 января 2008, 12:39
Был:9 апреля 2008, 19:55
lilo
smsup
Дата: 31 января 2008, 10:38 Сообщение № 3
в первом примере ошибка со скобками в 21 строке, должно быть
double w = (double)(1./(1.+(a*(*k)) /n* (a*(*k))) /n);