Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.80/5: Рейтинг темы: голосов - 5, средняя оценка - 4.80
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606

Численное интегрирование и его оптимизация

13.10.2023, 00:23. Показов 1393. Ответов 17

Студворк — интернет-сервис помощи студентам
Ну раз уж с Гауссом запорол программу, может и в интегрировании накосячил? Оптимизировал как мог, но, скорее всего, мой вариант с автошагом для Симпсона и Буля (хотя у нас его почему-то называли Боде) не самый оптимальный. Может кто подскажет словом или делом(кодом)?

Заголовочный файл
C++
1
2
3
4
5
6
7
8
9
10
#pragma once///////////////////////////////////////////////////////////////////////////
////////////////////////////INTEGRATE//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
 
double Simpson(double f_sh(double), double a, double b, int n = 64);//формула Симпсона (интегрирование)
double Simpson_auto(double f_sh(double), double a, double b, double eps = 1.e-9);//формула Симпсона (интегрирование с автошагом)
double bul(double f_sh(double), double a, double b, int n = 64);//формула Буля (интегрирование)
double bul_auto(double f_sh(double), double a, double b, double eps = 1.e-9);//формула Буля (интегрирование с автошагом)
 
double FAbs(double x);//модуль числа
Исходник
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
#include "diff.h"
 
 
double FAbs(double x)//модуль
{
    if(x > 0.)
        return x;
    return -x;
}
 
double Simpson(double f_sh(double), double a, double b, int n)//h*(f0+f2n+2*(f2k)+4*(f2k-1))/3
{//интеграл от функции
    int N = 2 * n;
    double integ = 0, h = (b - a) / N, x0 = a;
    integ = f_sh(b) + f_sh(a);
    for (int i = 1; i < N; i++)
    {
        x0 += h;
        integ += 2 * f_sh(x0) * ((i + 1) % 2) + 4 * f_sh(x0) * (i % 2);
    }
    return integ * h / 3;
}
 
 
double Simpson_auto(double f_sh(double), double a, double b, double eps)//h*(f0+f2n+2*(f2k)+4*(f2k-1))/3
{
    double res1 = Simpson(f_sh, a, b, 1);
    double res2 = Simpson(f_sh, a, b, 2);
    if (FAbs(res1 - res2) > eps)
        return Simpson_auto(f_sh, a, (a + b) / 2, eps) + Simpson_auto(f_sh, (a + b) / 2, b, eps);
    else
        return res2;
}
 
 
double bul(double f_sh(double), double a, double b, int n)//формула Буля (интегрирование)
{
    int N = 4 * n;
    double integ, h = (b - a) / N, x0 = a;
    integ = 7 * (f_sh(b) + f_sh(a));
    for (int i = 1; i < N; i++)
    {
        x0 += h;
        integ += 32 * f_sh(x0) * (i % 2) + 12 * f_sh(x0) * ((i - 2) % 4 ? 0 : 1) + 14 * f_sh(x0) * ((i - 4) % 4 ? 0 : 1);
    }
    return integ * 2 * h / 45;
}
 
 
double bul_auto(double f_sh(double), double a, double b, double eps)
{
    double res1 = bul(f_sh, a, b, 1);
    double res2 = bul(f_sh, a, b, 2);
    if (FAbs(res1 - res2) > eps)
        return bul_auto(f_sh, a, (a + b) / 2, eps) + bul_auto(f_sh, (a + b) / 2, b, eps);
    else
        return res2;
}
1
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.10.2023, 00:23
Ответы с готовыми решениями:

Численное интегрирование
Необходимо написать программу, которая считала бы площадь между двумя кривыми. Программа должна содержать: функции уравнений...

Численное интегрирование
Разработать программу «Численное интегрирование» различными методами: 1) по формуле трапеций; 2) по формуле Гаусса; 3) по формуле...

Численное интегрирование
Нужно реализовать вычисление интеграла по методу трапеций. // ConsoleApplication2.cpp : Defines the entry point for the console...

17
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 15:26  [ТС]
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
double FAbs(double x)//модуль
{
    if(x > 0)
        return x;
    return -x;
}
 
double bul(double f_sh(double), double a, double b, int n)//формула Буля (интегрирование)
{
    int N = 4 * n;
    double integ, h = (b - a) / N, x0 = a;
    integ = 7 * (f_sh(b) + f_sh(a));
    for (int i = 1; i < N; i++)
    {
        x0 += h;
        integ += 32 * f_sh(x0) * (i % 2) + 12 * f_sh(x0) * ((i - 2) % 4 ? 0 : 1) + 14 * f_sh(x0) * ((i - 4) % 4 ? 0 : 1);
    }
    return integ * 2 * h / 45;
}
 
 
double bul_auto(double f_sh(double), double a, double b, double eps)
{
    double h2 = (b - a) / 8, h1 = h2 + h2;//для меньшего кол-ва операций деления
    double f2 = f_sh(a + h1), f4 = f_sh(a + h1 + h1), f6 = f_sh(b - h1);//для меньшего количества вызовов функции
    double res1 = 7 * (f_sh(b) + f_sh(a)) + 32 * (f2 + f6) + 12 * f4;//почти что интеграл с шагом h1
    double dr = 32 * (f_sh(a + h2) + f_sh(a + h1 + h2) + f_sh(b - h1 - h2) + f_sh(b - h2)) - 20 * (f2 + f6) + 2 * f4;// разница почти что интегралов с шагом h1 и h2
    double res2 = (res1 + dr) * h1 / 45; res1 *= 2 * h1 / 45;//вот теперь это интегралы с шагом h2 и h1
    if (FAbs(res2 - res1) > eps)
        return bul_auto(f_sh, a, (a + 2 * h1), eps) + bul_auto(f_sh, (a + 2 * h1), b, eps);
    else
        return res2;
}
немного похимичил и реализовал расчёт интеграла на основе уже найденного результата, скорость ощутимо возросла, но хотелось бы ещё ускорить (этак в раз 5), есть ли у кого какие идеи?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 15:59
programmer_08, есть вот такой код

https://www.geeksforgeeks.org/... oles-rule/
1
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 16:16  [ТС]
Royal_X,
Цитата Сообщение от Royal_X Посмотреть сообщение
https://www.geeksforgeeks.org/... oles-rule/
но тут же просто приведён пример реализации формулы Буля, даже не составной... Или там ещё куда-то нужно тыкнуть (а на английском я могу и не увидеть)?
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 16:24
Цитата Сообщение от programmer_08 Посмотреть сообщение
не самый оптимальный
Какие у вас критерии оптимальности? Вы же ничего не пишете о самой задаче, которую решаете. Что за интеграл? Зачем вы выбрали конкретно этот метод? Откуда вы взяли формулу (или код)? Для чего вам всё это?

В общем могу сказать лишь то, что не существует универсального одного самого лучшего метода численного интегрирования. Один метод хорош для одного интеграла, а другой для другого. По этой причине, в мат. пакетах, как правило, функция численного интегрирования по очереди пробует разнообразные методы и выбирает тот, который лучше справляется с интегралом.
1
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 16:31  [ТС]
Цитата Сообщение от Royal_X Посмотреть сообщение
Какие у вас критерии оптимальности
скорость счёта интеграла от функции sin^2(x) - ln(x^2) на интервале от 0.1 от 10 (10000 итераций проходит за 1300 милисекунд, а хотелось бы за 300-400, если возможно)
Цитата Сообщение от Royal_X Посмотреть сообщение
Откуда вы взяли формулу (или код)
Формулу с вики
Цитата Сообщение от Royal_X Посмотреть сообщение
Зачем вы выбрали конкретно этот метод
См. таблицу
Миниатюры
Численное интегрирование и его оптимизация  
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 17:21
Цитата Сообщение от programmer_08 Посмотреть сообщение
функции sin^2(x) - ln(x^2) на интервале от 0.1 от 10
это функция интегрируется и без численных методов

https://www.cyberforum.ru/cgi-bin/latex.cgi?\int \sin ^2(x)-\ln \left(x^2\right)\, dx= x \left(-\ln \left(x^2\right)\right)+\frac{5 x}{2}-\frac{1}{4} \sin (2 x)

Соответственно,

https://www.cyberforum.ru/cgi-bin/latex.cgi?\int_{0.1}^{10}\sin ^2(x)-\ln \left(x^2\right)\, dx=\frac{1}{4} \left(99-\sin (20)+\sin \left(\frac{1}{5}\right)\right)-\frac{101\, \ln (10)}{5}

Касательно таблицы, то эта таблица ни о чем не говорит. Там точность для одной итерации. Да, одна итерация навороченного метода дает более точный результат, чем одна итерация простенького метода. Но ведь нужно учитывать, что у навороченного метода в ходе одной итерации происходит больше арифметических операций, чем в ходе одной итерации простенького метода. Соответственно, одна итерация навороченного метода занимает больше времени, чем одна итерация простенького метода.

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

Еще вы не написали, какая точность результата вам нужна?
1
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 17:30  [ТС]
Цитата Сообщение от Royal_X Посмотреть сообщение
Еще вы не написали, какая точность результата вам нужна
считаю с точностью 1.e-10
Цитата Сообщение от Royal_X Посмотреть сообщение
Соответственно, одна итерация навороченного метода занимает больше времени, чем одна итерация простенького метода.
ну для достижения одной и той же точности метод Симпсона тратит больше времени, нежели метод Буля
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 17:49
programmer_08, попробуйте этот код с простеньким методом. Уж точно укладывается в ваше желаемое время:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <cmath>
 
double trapezoidal(double (*f)(double), double a, double b, int n) {
    double h = (b-a)/n;
    double sum = 0.5*(f(a) + f(b));
    for (int i = 1; i < n; i++) {
        double x = a + i*h;
        sum += f(x);
    }
    return h*sum;
}
 
 
int main()
{
    auto f = [](double x){return std::pow(std::sin(x),2.)-std::log(x*x);};
    std::cout.precision(12);
    std::cout << trapezoidal(f, 0.1, 10., 1300000);
}
-21.9407878584
1
2622 / 1633 / 266
Регистрация: 19.02.2010
Сообщений: 4,334
14.10.2023, 18:01
Цитата Сообщение от programmer_08 Посмотреть сообщение
скорость счёта интеграла от функции sin^2(x) - ln(x^2)
зависит в первую очередь от времени вычисления sin(), log() - а не от арифметики внутри метода интегрирования.
Ибо если процессорная команда fsin жрёт порядка сотни процессорных тактов - то на число сложений-умножений в одном шаге схемы интегрирования уже по барабану (команды fadd, fmul выполняются за 3-5 тактов каждая).

Цитата Сообщение от Royal_X Посмотреть сообщение
попробуйте этот код с простеньким методом. Уж точно укладывается в ваше желаемое время:
programmer_08, ускорение получено за счёт снижения числа вычислений интегр.функции на каждом шаге интегрирования с 9 до 1, т.е. на порядок. Так что при данной интегр.функции влияет именно сам метод (сколько раз он вызывает интегр.функцию), а не прочая арифметика внутри него.
0
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 18:21  [ТС]
Royal_X,
Цитата Сообщение от Royal_X Посмотреть сообщение
Уж точно укладывается в ваше желаемое время
Возможно я неправильно выразился, но 10000 итерации это 10000 вычислений интеграла по промежутку

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
#include <iostream>
#include <ctime>
#include "MyMath/diff.h"
 
using namespace std;
 
double f(double x)
{
    return sin(x) * sin(x) - log(x * x);
}
 
double trapezoidal(double (*f)(double), double a, double b, int n) {
    double h = (b - a) / n;
    double sum = 0.5 * (f(a) + f(b));
    for (int i = 1; i < n; i++) {
        double x = a + i * h;
        sum += f(x);
    }
    return h * sum;
}
 
int main()
{
    time_t start, finish;
    double a = 0.1, b = 10., eps = 1.e-10;
    int n = 10000;
 
    start = clock();
    for (int i = 0; i < n; i++)
        bul_auto(f, a, b, eps);
    finish = clock();
    cout << "\n" << finish - start << "\n\n" << bul_auto(f, a, b, eps) << "\n\n";
    printf("EPS < %e", eps);
 
    start = clock();
    for (int i = 0; i < n; i++)
        trapezoidal(f, a, b, 4096);
    finish = clock();
    cout << "\n" << finish - start << "\n\n" << bul_auto(f, a, b, eps) << "\n\n";
 
    //printf("%e", FAbs(trapezoidal(f, a, b, 4096) - bul_auto(f, a, b, eps)));
 
    printf("EPS = %e", FAbs(trapezoidal(f, a, b, 4096) - trapezoidal(f, a, b, 4096*2)));
 
    return cin.get();
}
даже при разбиении отрезка на 4096 отрезков точность далека от желаемой, а время превышает время при использовании метода Буля с автоматическим подстраиванием шага
Изображения
 
1
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 18:26  [ТС]
вот поэтому и акцентирую внимание на оптимизации автоматического шага, можно ли ещё оптимизировать его, потому что, пока что, я смог уменьшить кол-во вызовов интегрируемой функции за счёт переменных f2,f4 и f6. Есть ли ещё идеи в этом направлении? В целом если найдётся более быстрый метод - это хорошо, но если ускорить методику автоматического подстраивания шага, то это уже ускорит любой другой метод, к которому она может быть применена.
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 18:45
programmer_08, я неверно растолковал вашу фразу

Цитата Сообщение от programmer_08 Посмотреть сообщение
10000 итераций проходит за 1300 милисекунд, а хотелось бы за 300-400
подумав, что вам нужно найти интеграл с точностью 1.e-10 за 300-400 мс

Мне эти ваши итерации ни о чем не говорят. Итерация может быть сложной, а может простой. Итерация одного метода может давать одну точность, а другого другую.

По этой причине, лучше бы вы указали, за какое время вы хотите найти данный интеграл с точностью 1e-10? И за какое время находит его ваш код с методом Буля?
0
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 19:20  [ТС]
Цитата Сообщение от Royal_X Посмотреть сообщение
По этой причине, лучше бы вы указали, за какое время вы хотите найти данный интеграл с точностью 1e-10? И за какое время находит его ваш код с методом Буля?
интеграл хочу посчитать с точностью 1.e-10 за время 0,03-0,04 миллисекунды, мой код считает его за 0,13 миллисекунд

просто измерять микросекунды я не умею, поэтому и запихиваю в цикл на 10000 вычислений
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
14.10.2023, 19:46
Цитата Сообщение от programmer_08 Посмотреть сообщение
хочу посчитать с точностью 1.e-10 за время 0,03-0,04 миллисекунды, мой код считает его за 0,13 миллисекунд
может секунд?
0
фрилансер
 Аватар для Алексей1153
6444 / 5637 / 1128
Регистрация: 11.10.2019
Сообщений: 14,997
14.10.2023, 19:55
Цитата Сообщение от Royal_X Посмотреть сообщение
auto f = [](double x){return std:: pow(std::sin(x),2.)-std::log(x*x);};
если эту лямбду перетащить внутрь функции trapezoidal, то ещё шустрее отработает
2
 Аватар для programmer_08
687 / 444 / 209
Регистрация: 18.10.2020
Сообщений: 1,606
14.10.2023, 20:28  [ТС]
Royal_X, именно что миллисекунд, если мы говорим об единоразовом подсчёте интеграла.
0
Эксперт функциональных языков программированияЭксперт С++
 Аватар для Royal_X
6132 / 2827 / 1038
Регистрация: 01.06.2021
Сообщений: 10,311
16.10.2023, 16:48
programmer_08, только заметил, что вы меряете время выполнения кода функцией clock, что означает, что вы меряете процессорное время (CPU time). Надеюсь, вы это делаете осознанно.
Очень важно понимать разницу между функциями:
clock
std::chrono::steady_clock
std::chrono::system_clock
std::chrono::high_resolution_clock
std::chrono::utc_clock
std::chrono::tai_clock
std::chrono::gps_clock
std::chrono::file_clock
Для измерения времени выполнения части кода я советую использовать:
std::chrono::high_resolution_clock, если is_steady выдает true,
иначе использовать
std::chrono::steady_clock.
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
16.10.2023, 16:48
Помогаю со студенческими работами здесь

Численное интегрирование
Помогите пожалуйста. Нужно написать программу для вычисления интегральных функций ctgx пятью методам: 1. Метод Симпсона 2. Средних ,...

Численное интегрирование функции
Составить программу...

Численное интегрирование по формуле трапеций
Доброго времени суток форумчане, обращаюсь к вам за помощью, прошу сильно камнями не кидаться. В общем суть проблемы такова:...

Разработать программу «Численное интегрирование»
Разработать программу «Численное интегрирование» различными методами: 1) по формуле трапеций; 2) по формуле Гаусса; 3) по формуле...

Численное интегрирование методом трапеций
Найти ошибки в программе #include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;iomanip&gt; #include &lt;cmath&gt; #include &lt;math.h&gt; ...


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

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение/ Перевод https:/ / **********/ gallery/ thinkpad-x220-tablet-porn-gzoEAjs . . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru