Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
0 / 0 / 0
Регистрация: 20.04.2022
Сообщений: 2
1

Метод деления отрезка пополам

22.04.2022, 19:54. Показов 484. Ответов 4
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день. На одной из лаб надо найти корни двух уравнений методом деления отрезка пополам. Все сделал, считает правильно, корни ищет, наблюдаю непонятный эффект - для двух разных уравнений число итераций одинаково. Другим методом (простые итерации) число итераций разное. В чем ошибка?
PS Классы, потоки и конвейеры использовать было нельзя - ограничение препа для 1 курса. Только функциональное программирование.

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//---------------------------------------------------------------------------
#include <stdio.h>  // printf, scanf
#include <conio.h>  // getch
#include <math.h> // Математические функции (sin cos atan exp pow и т.д.) и константа Пи - M_PI
#include <windows.h>
#include <stdlib.h>
 
 
//---------------------------------------------------------------------------
 
 
double my_f1(double x){  // функция вариант 1 (один параметр типа double и результат double)
    return (pow(4,1.0/3)-pow(sin(x/10),2))/pow(x,1.0/2)-x;
}
 
double my_f4(double x){  // функция вариант 4 (один параметр типа double и результат double)
    return 1.5-(pow(x,1.0/2)+pow(x,1.0/3))/exp(3.0/2)-x;
}
 
double check_root(double a, double b, double (*f)(double))
{
    double fa = f(a), fb = f(b);
    if (fa*fb > 0) { printf("Корня на отрезке AB нет\n"); return 0; }
    else return 1;
}
 
double root_half(double a, double b, double (*f)(double), double eps, double &c, int &iter )
{
    double fa = f(a);
    do{
        c=(a+b)/2.0;
        double fc = f(c);
        if (fc*fa > 0) { a = c; } else { b = c; }
        iter++;
    } while (fabs(b-a)>=eps && iter <=2000);
    return 0;
}
double simple_iter(double a, double b, double (*f)(double), double eps, double &c, int &iter )
{
    double x0,x1,delta;
    x0=(a+b)/2.0;  //стартовое значение - середина отрезка ab
 
    do {
        x1=x0+0.5*f(x0);
        delta=fabs(x1-x0);
        x0=x1;
        iter++;
    } while (delta>=eps && iter<=2000);
    c=x1;
    return 0;
}
 
 
void print_header(int NFunc)
{
int i;
 
for (i=1; i < 80; i++) printf("="); printf("\n");
printf("| Функция №%d  |            Метод деления        |         Метод простых       |\n",NFunc);
printf("| Погрешность |           отрезка пополам       |            итераций         |\n");
for (i=1; i < 80; i++) printf("="); printf("\n");
printf("|             |    Корень      |   Итераций     |    Корень     |   Итераций  |\n");
for (i=1; i < 80; i++) printf("="); printf("\n");
}
 
 
 
void main()
{
    SetConsoleOutputCP(1251);
    int i,n,z, iter1 = 0 , iter2=0, iter3 = 0,iter4= 0;
    double a, b, root1=0, root2=0; // вещ.число с плавающей точкой двойной точности
    double eps = 0.1; //стартовая погрешность
    //вводим исходые данные
 
    printf("N (от 1 до 10)=? ");
    scanf("%d", &n);  // ввод десятичного(%d) n - целое число
    if (n<1 || n>10) {
        printf("Недопустимое значение N\n");
        printf("\nPress any key to exit");  getch(); return;
    }
    printf("Введите значение A (0<A<2) ");
    scanf("%lf", &a);  // ввод A - вещественное число;
    if (a<=0 || a>=2) {
        printf("Недопустимое значение A\n");
        printf("\nPress any key to exit");  getch(); return;
    }
    printf("Введите значение B (0<A<B<2) ");
    scanf("%lf", &b);
    if (b<=0 || b>=2 || b<=a) {
        printf("Недопустимое значение B\n");
        printf("\nPress any key to exit");  getch(); return;
    }
 
 
    print_header(1);
    if (!check_root(a,b,my_f1)==0) {
      for (i=1; i <= n; i++) {
        root_half(a,b,my_f1,eps, root1, iter1);
        simple_iter(a,b,my_f1,eps, root2, iter2);
        z = ceil(fabs(log(eps)/log(10.0)));
        printf("| %-12.*lf|  %-12.*lf  |     %4d       |  %-12.*f |    %4d     |\n",z, eps,z, root1,iter1,z, root2,iter2);
        eps = eps/10.0;
      }
    }
    //сбрасываем погрешность и итерации перед вторым вариантом
    eps = 0.1;
    print_header(4);
    if (!check_root(a,b,my_f4)==0) {
      for (i=1; i <= n; i++) {
        root_half(a,b,my_f4,eps, root1, iter3);
        simple_iter(a,b,my_f4,eps, root2, iter4);
        z = ceil(fabs(log(eps)/log(10.0)));
        printf("| %-12.*lf|  %-12.*lf  |     %4d       |  %-12.*lf |    %4d     |\n",z,eps,z, root1, iter3 ,z,root2,iter4);
        eps = eps/10;
      }
    }
 
 
    printf("\nPress any key to exit");  getch(); // задержка консольного экрана до нажатия любой клавиши
    return; //выход из main()
}
//---------------------------------------------------------------------------
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2022, 19:54
Ответы с готовыми решениями:

Метод деления отрезка пополам
Здравствуйте, нужно реализовать метод деления отрезка пополам. Дано уравнение: x3-5x2+2x+8=0 и...

Метод деления отрезка пополам
Помогите!! Написать функцию,выполняющую поиск корня уравнения f(x)=0 методом деления отрезка...

Метод «деления отрезка пополам»
Доброе время суток! Помогите, пожалуйста, довести программу до ума. Итерационный процесс будет...

Метод деления отрезка пополам для решения нелинейных уравнений (метод дихотомии)
Здравствуйте. Помогите пожалуйста дописать программу. Вот что вымучал, но на сдаче завалили, типо...

метод деления отрезка пополам и метод итерации
Методом деления отрезка пополам и методом итерации найти приближенное значение корня 2*x^3+3*x-1=0 ...

4
Модератор
Эксперт С++
13507 / 10757 / 6412
Регистрация: 18.12.2011
Сообщений: 28,712
22.04.2022, 20:20 2
Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
Другим методом (простые итерации) число итераций разное
А почему оно должно быть одинаковое?
Это просто случайное совпадение в 1 случае.
0
0 / 0 / 0
Регистрация: 20.04.2022
Сообщений: 2
22.04.2022, 20:38  [ТС] 3
Нет, проверено на разных отрезках и для разной точности. Даже функции(уравнения) менял. Строго одинаковое число итераций для 2х разных функций на одном отрезке для данного метода. На том же отрезке для второго метода (простых итераций) число итераций разное.

C++
1
2
3
double my_f1(double x){  // функция вариант 1 (один параметр типа double и результат double)
    return (pow(4,1.0/3)-pow(sin(x/10),2))/pow(x,1.0/2)-x;
    //return (log(44.8)-sin(pow(x,1.0/2)))/2-x;
0
48 / 37 / 14
Регистрация: 23.12.2015
Сообщений: 188
22.04.2022, 23:11 4
Pavel_Soklakov,
quote="Pavel_Soklakov;16192323"]Строго одинаковое число итераций для 2х разных функций на одном отрезке для данного метода.[/quote]

Эм, а не все ли Верно?
Что такое метод деления отрезка.
1. Пусть уже есть отрезок, на котором корень заведомо есть (с одной стороны функция минус, с другой плюс).
2. Вычисляем значение функции в центре отрезка, ну и по результату сокращаем отрезок в два раза.
3. Благодаря "страшной силе экспоненты" за лишь десятки (ну максимум сотни если уж очень точно искать. и то вряд ли надо) итераций находим с высокой точностью.

Ну и ты "нужную точность" считаешь видимо тут
while (fabs(b-a)>=eps && iter <=2000);
Т.е. когда отрезок станет достаточно коротким. Ну а так как он каждую итерацию сокращается в два раза, то и получается тот эффект, который тебя удивляет.

***

Ну а "простые итерации" это я не помнил наизусть, но посмотрел в вики
Идея метода простой итерации состоит в том, чтобы уравнение f ( x ) = 0 привести к эквивалентному уравнению

x = φ ( x )

так, чтобы отображение φ ( x ) было сжимающим. Если это удаётся, то последовательность итераций x i + 1 = φ ( x i ) сходится.

Разумеется знаю про такой метод.
Он да, понятно принципиально завязано на конкретную функцию, насколько быстро сойдется.

Добавлено через 5 минут
zss, Т.е. я думаю, что автор темы все верно посчитал, и из свойств метода деления отрезка так и должно быть.
Но не настаиваю безапелляционно.

Вопрос как к модератору.
Может перенести тему в
https://www.cyberforum.ru/numerical-methods/
Так как такие общие свойства методов деления отрезка и метода простых итераций - это вычислительная математика, а не плюсы?
0
Вездепух
Эксперт CЭксперт С++
11694 / 6373 / 1723
Регистрация: 18.10.2014
Сообщений: 16,066
23.04.2022, 00:06 5
Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
наблюдаю непонятный эффект - для двух разных уравнений число итераций одинаково.
Что ж тут непонятного? Один и тот же отрезок делится пополам, пока остаток не станет меньше некоего эпсилон. От решаемого уравнения этот процесс вообще нигде и никак не зависит. То есть не только не "непонятно", а всем, включая вас, совершенно очевидно (!), что количество итераций для одного и того же отрезка и одного и того же эпсилон всегда будет одно и то же.

Зачем вы выдумываете сказки про про какой-то "непонятный эффект"?

В методе простых итерацией способ деления отрезка у вас зависит от решаемого уравнения, поэтому там число итераций будет разным для разных уравнений. Все очевидно.

Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
void main()
Распространенные ошибки

Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
return; //выход из main()
}
Зачем "выходить из main", когда функция и так заканчивается?

Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
double check_root(double a, double b, double (*f)(double))
Почему эта функция возвращает double???

Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
C++
1
2
double root_half(double a, double b, double (*f)(double), double eps, double &c, int &iter )
double simple_iter(double a, double b, double (*f)(double), double eps, double &c, int &iter )
В чем назначение возвращаемых значений этих функций?

Цитата Сообщение от Pavel_Soklakov Посмотреть сообщение
Только функциональное программирование.
Термин "функциональное программирование" не имеет ничего общего с написанием С++ программ только из функций.
1
23.04.2022, 00:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.04.2022, 00:06
Помогаю со студенческими работами здесь

Визуальное программирование. Метод деления отрезка пополам
Приближенное нахождение решения уравнения f(x)=0 методом деления отрезка пополам. Написать...

Минимум Функции (метод деления отрезка пополам)
Подскажите пожалуйста, Мне нужно найти методом деления отрезка пополам минимум функции одной...

2 Программы. На "целые числа и системы счисления" и на "метод деления отрезка пополам"
1)Дано натурально число n. Среди чисел 1, ... ,n найти все такие, запись которых совпадает с...

Ошибка в методе деления отрезка пополам
Программа выдаёт значение, которое находится далеко от точности, в чём ошибка? #include &lt;iostream&gt;...

Поиск экстремума методом деления отрезка пополам
Выдаёт ошибку в 15 строчке. Не могу понять в чём дело, помогите) #include&lt;iostream&gt; ...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru