Форум программистов, компьютерный форум, киберфорум
Численные методы
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.71/21: Рейтинг темы: голосов - 21, средняя оценка - 4.71
0 / 0 / 1
Регистрация: 02.02.2011
Сообщений: 114
1

Метод Ньютона (Метод касательных) для решения нелинейных уравнений

24.12.2013, 09:59. Показов 4387. Ответов 9
Метки нет (Все метки)

Преподаватель дал задание: Реализовать метод ньютона для решения нелинейных уравнений. Пробежался по литературе, реализовал метод. НО Почему у метода такие жёсткие условия сходимости? к примеру f(x)' и f(x)'' не должны менять знака. т.е. функции sin и cos методом уже не вычислить. Подскажите для каких функций использовать метод? Преподаватель сказал что можно сделать так, чтоб считался и sin, и cos, и любые другие функции. К примеру если убрать условие сходимости (f(x)' и f(x)'' не должны менять знака) и ввести промежуток [0,2] то функцию sin считает правильно, 3.14.... и косинус тоже, в общем так считает любые функции у которых только один корень. У тригонометрических вычисляет только первый корень. Преподаватель хочет чтоб программа находила все нули функции, какую бы туда не вбили. Завтра нужно сдавать уже, подскажите как это сделать?
Кликните здесь для просмотра всего текста

C++ (Qt)
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
void __fastcall TForm1::Button8Click(TObject *Sender)
{
double a=(Edit3->Text).ToDouble();
double b=(Edit4->Text).ToDouble();
double R=a-b;
int h=0;
for(int l=a;l<b;l++)
{
 if(pro(l)<0) {h++;}
 if(pro(pro(l))<0) {h++;}
}
if(h>0){ShowMessage("h>0");}
String str=Edit2->Text;
String str1=NULL;
double x9;
  double epsilon=0.001;
  double x0;
   // Если F(a)*F"(a)>0, x0=a, в противном случае x0=b.
  if(calc(a)*pro(pro(a))>0){x9=a;}
  else(x9=b);
  if(str=="x")
  {
  Label15->Caption=str1;
  }
  else{
  do
  {
    x0=x9;
     x9=x9-(calc(x9)/pro(x9));
  } while (fabs(x0-x9)>epsilon);
Label15->Caption=FloatToStr(x9);
 }
}
//----------


функция pro(); вычисляет значение производной функции в точке по определению.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.12.2013, 09:59
Ответы с готовыми решениями:

Метод Ньютона для решения систем нелинейных уравнений.
Существуют ли алгоритмы, методы выбора начального приближения для метода Ньютона? Задача такая:...

Метод Ньютона для решения системы нелинейных уравнений
sin(x+2)-y=1.5 x+cos(y-2)=0.5 решить методам Ньютона с погрешностью 0.0001.За начальные...

Метод Ньютона для решения систем нелинейных уравнений с 3 неизвестными
Собственно интересует каким образом можно найти начальное приближение X(0)

Метод простой итерации для решения нелинейных уравнений
Помогите, пожалуйста, решить задачу: с точностью 10^(-8) найти все действительные корни уравнения...

9
Модератор
Эксперт по математике/физике
4189 / 3368 / 395
Регистрация: 15.06.2009
Сообщений: 5,766
24.12.2013, 13:28 2
Цитата Сообщение от Yazu Посмотреть сообщение
Почему у метода такие жёсткие условия сходимости? к примеру f(x)' и f(x)'' не должны менять знака
Странный вывод. Откуда это? Где прочитано?

См. Березин, Жидков, Методы вычислений, т.1.

В коде: строки 6, 7 - почему переменные целого типа?
Тестовые примеры: 4x2 - 1 = 0; 8x3 - 1 = 0 на интервале (0; 1)
0
0 / 0 / 1
Регистрация: 02.02.2011
Сообщений: 114
24.12.2013, 13:33  [ТС] 3
Разобрался с решением, теперь есть другой вопрос. Нужно произвести отделение кореней. написал такую функцию, к ней сразу всё прилагаю в коде. Но не работает. для начала не хочет искать производную от нуля, а во вторых почему-то при функции синус всегда отрицательные значения.
Кликните здесь для просмотра всего текста

C++ (Qt)
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
double pro (double x2)
  {
   double e1=0.001;
   double diff = 0.0000001;
    double R,R1,dx=0.1,delta;
    double n7;
    n7=x2+diff;
    R=(calc(n7)-calc(x2))/dx;
    do
     {
      dx=dx/10;
      R1=R;
      n7=x2+dx;
      R=(calc(n7)-calc(x2))/dx;
      delta=fabs(R-R1);
     }
     while(delta>=e1);
    return R;
  }
 
  struct massiv
  {
   double *mas;
   int raz;
  };
  massiv toch;
 
void otdel(double a, double b,double epsilon)
  {
  int h=0;
   do
   {
    if(pro(a-0.1)*pro(a+0.1)<=0) {toch.mas[h]=a; h++;}
    a=a+0.1;
   }while(a!=b);
   toch.raz=h;
  }


Добавлено через 3 минуты
Цитата Сообщение от Том Ардер Посмотреть сообщение
Странный вывод. Откуда это? Где прочитано?

См. Березин, Жидков, Методы вычислений, т.1.

В коде: строки 6, 7 - почему переменные целого типа?
Тестовые примеры: 4x2 - 1 = 0; 8x3 - 1 = 0 на интервале (0; 1)
прочитанно вот тут: http://edu.dvgups.ru/METDOC/EN... rame/3.htm

Посмотрите пожалуйста предыдущее моё сообщение. В этом сейчас основная проблема.

Добавлено через 2 минуты
Забыл написать, функция calc() вычисляет значение функции в точке, которую передаём.
0
Модератор
Эксперт по математике/физике
4189 / 3368 / 395
Регистрация: 15.06.2009
Сообщений: 5,766
24.12.2013, 14:00 4
Код: вычисление производной - какие-то головоломки с циклами. Явное нарушение простой логики.
Строки 23, 33: типичная ошибка с указателями. Указатель объявлен, память для массива не выделена.

Цитата Сообщение от Yazu Посмотреть сообщение
pro(a-0.1)*pro(a+0.1)
выход за пределы начального интервала, возможны любые ошибки.

В ссылке всё правильно, только понято всё не то и не так. И реализовано в коде как понято.
0
0 / 0 / 1
Регистрация: 02.02.2011
Сообщений: 114
24.12.2013, 14:05  [ТС] 5
Цитата Сообщение от Том Ардер Посмотреть сообщение
Код: вычисление производной - какие-то головоломки с циклами. Явное нарушение простой логики.
Строки 23, 33: типичная ошибка с указателями. Указатель объявлен, память для массива не выделена.

выход за пределы начального интервала, возможны любые ошибки.

В ссылке всё правильно, только понято всё не то и не так. И реализовано в коде как понято.
В pro() только один do{}while; и только для того, чтоб считать с определённой точностью. Функцию тестировал уже во многих программа, до этого всё отлично работало. Думаю дело не в функции. А по поводу выхода за пределы интервала, можете подсказать как определять точки в которых заданная функция =0? У меня просто идеи кончились уже.
0
Модератор
Эксперт по математике/физике
4189 / 3368 / 395
Регистрация: 15.06.2009
Сообщений: 5,766
24.12.2013, 14:21 6
Простейший способ отделения нулей - табличный, сразу определяется и начальный интервал для уточнения каждого корня.
0
0 / 0 / 1
Регистрация: 02.02.2011
Сообщений: 114
24.12.2013, 16:26  [ТС] 7
Цитата Сообщение от Том Ардер Посмотреть сообщение
Простейший способ отделения нулей - табличный, сразу определяется и начальный интервал для уточнения каждого корня.
Сделал отделение корней, оно работает теперь верно и всё нормально считается. остался последний косяк. Как правильно выбирать начальное приближение? Я уже несколько способов попробовал, результат вычислений меняется. тестирую на sin(x)=0 на интервале [1,10] и то первый корень верно, остальные 2 нет, то наоборот. подскажите как выбирать начальное приближение?

Добавлено через 7 минут
при таком приближении:
if(calc(b)*pro(pro(b))>0){x9=b;}
else(x9=a);
корни: 3.14 3.14 15.70

при таком: (b-a)/2
корни: -5.87 -5.87 -5.87

при таком: b
корни: 3.14 9.42 15.70
0
Модератор
Эксперт по математике/физике
4189 / 3368 / 395
Регистрация: 15.06.2009
Сообщений: 5,766
24.12.2013, 17:04 8
Цитата Сообщение от Yazu Посмотреть сообщение
тестирую на sin(x)=0 на интервале [1,10]
После отделения корней получается несколько разных интервалов, на каждом из которых заведомо только один корень. А дальше уточнять корень для каждого отдельного подинтервала. Начальным приближением может быть или середина интервала, т.е. https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{a+b}{2}, или точка, в которой хорда, проходящая через https://www.cyberforum.ru/cgi-bin/latex.cgi?\left((a,f(a);(b,f(b) \right), пересекает ось абсцисс.
1
0 / 0 / 1
Регистрация: 02.02.2011
Сообщений: 114
24.12.2013, 17:18  [ТС] 9
Цитата Сообщение от Том Ардер Посмотреть сообщение
После отделения корней получается несколько разных интервалов, на каждом из которых заведомо только один корень. А дальше уточнять корень для каждого отдельного подинтервала. Начальным приближением может быть или середина интервала, т.е. https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{a+b}{2}, или точка, в которой хорда, проходящая через https://www.cyberforum.ru/cgi-bin/latex.cgi?\left((a,f(a);(b,f(b) \right), пересекает ось абсцисс.
Сделал так (код ниже). синус, косинус считает нормально. для примера взял функцию x^2-4*x+4=0 посчитал нормально, а вот x^2-5*x+4=0-прога висит. т.е. квадратные уравнения с 2 корнями не хочет считать. промежуток брал [0,10]

код:

Кликните здесь для просмотра всего текста

C++ (Qt)
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
//---------------------------------------------------------------------------
double pro (double x2)
  {
   double e1=0.001;
   double diff = 0.0000001;
    double R,R1,dx=0.1,delta;
    double n7;
    n7=x2+diff;
    R=(calc(n7)-calc(x2))/dx;
    do
     {
      dx=dx/10;
      R1=R;
      n7=x2+dx;
      R=(calc(n7)-calc(x2))/dx;
      delta=fabs(R-R1);
     }
     while(delta>=e1);
    return R;
  }
 
  struct massiv
  {
   double *toch;
   double *pr;
   int h;
  };
  massiv toch;
 
void otdel(double a, double b,double epsilon)
  {
  int h=0;
  double a1=a;
   do
   {
    a1=a1+1.5;
    h++;
   }while(a1!=b);
 
  double *toch1;
  toch1=new double [h];
 
  double *pr1;
  pr1=new double [h];
 
  h=0;
  a1=a;
   do
   {
    toch1[h]=a1;
    a1=a1+1.5;
    //a1=a1+1.5;
    h++;
   }while(a1!=b);
 
  for(int i1=0;i1<h;i1++)
  {
   pr1[i1]=pro(toch1[i1]);
  }
 toch.toch=toch1;
 toch.pr=pr1;
 toch.h=h;
 Form1->StringGrid4->RowCount=h;
  Form1->StringGrid6->RowCount=h;
 
  for(int i1=0;i1<h;i1++)
  {
    Form1->StringGrid4->Cells[0][i1]=FloatToStr(pr1[i1]);
    Form1->StringGrid6->Cells[0][i1]=FloatToStr(toch1[i1]);
  }
 
}
 
 
void __fastcall TForm1::Button8Click(TObject *Sender)
{
double a=(Edit3->Text).ToDouble();
double b=(Edit4->Text).ToDouble();
double epsilon=(Edit5->Text).ToDouble();
otdel(a,b,epsilon);
 
StringGrid5->RowCount=toch.h-1;
int jo=0;
for(int i1=0;i1<toch.h-1;i1++)
{
if(toch.pr[i1]*toch.pr[i1+1]<0)
{
 a=toch.toch[i1];
 b=toch.toch[i1+1];
 int h=0;
 double x9;
 double x0;
 double c;
 
x9=b;
 
 
  do
  {
    x0=x9;
     x9=x9-(calc(x9)/pro(x9));
  } while (fabs(x0-x9)>epsilon);
 StringGrid5->Cells[0][jo]=FloatToStr(x9);
 jo++;
 }
}
}
//-------------------
0
Модератор
Эксперт по математике/физике
4189 / 3368 / 395
Регистрация: 15.06.2009
Сообщений: 5,766
24.12.2013, 17:40 10
Цитата Сообщение от Yazu Посмотреть сообщение
прога висит.
По огрызкам кода о причине сказать ничего нельзя. Отлаживайте - точки останова, трассировка, промежуточные результаты, учитесь.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.12.2013, 17:40

Можно ли расширить метод Ньютона на систему нелинейных уравнений
Можно ли расширить метод Ньютона на систему нелинейных уравнений?

Метод ньютона(метод касательных)
Найти корень уравнения на заданном интервале {a,b} с точностью эпсилом=0,00001 (x-1)^(2)-0,5е^...

Метод Ньютона для решения уравнения.
Здравствуйте помогите пожалуйста сделать уравнение, завтра уже сдавать !!!! Заранее...

Трансцендентные уравнения. Метод Ньютона(касательных)
Добрый день, всем форумчанам. Вот такой вопрос. Мне бы литературы подкинуть где описывают...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru