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

Большая погрешность в вычислении длины кривой - C++

Восстановить пароль Регистрация
 
almalexia1997
0 / 0 / 0
Регистрация: 15.09.2014
Сообщений: 16
19.11.2016, 04:22     Большая погрешность в вычислении длины кривой #1
Есть задание: вычислить длину контура эллипса. Входные данные - коэффициенты a и b из канонического уравнения и n - количество точек для таблицы значений функции. Количество точек к сожалению только 20 программа осиливает. Я набираю в вольфраме команду "arc length y = 5*sqrt(1-x^2/16), x=-4,4" которая высчитывает длину кривой. Но моя программа высчитывает длину кривой с довольно сильной погрешностью: на вольфе: 14,1808, а у меня:13,6447. В чем дело, почему такая погрешность большая? Длину кривой я считаю стандартной формулой криволинейного интеграла http://www.cyberforum.ru/cgi-bin/latex.cgi?\int_{L}dl = \int_{a}^{b}\sqrt{1+y'(x)^{2}}dx.
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
124
125
#include <iostream>
#include <iomanip>
#include <vector>
 
using namespace std;
 
double f(double x, double a, double b){ //+
    return sqrt(1 - x*x / (a*a))*b;
}
 
double df_dx(double x ,double a, double b){
    return -b*x / (a*a*sqrt(1-x*x/(a*a)));
}
 
double dL(double x, double n, vector<double> x_arr, vector<double> y_arr){//Это приближенное значение производной ~
    //Формула численного дифференцирования
    double sum1 = 0;
    for (int i = 0; i < n; ++i){
 
        double sum2 = 0;
        for (int j = 0; j < n; ++j){
            if (j != i){
                double p = 1;
                for (int k = 0; k < n; ++k)
                if (k != i && k != j)
                    p *= (x - x_arr[k]) / (x_arr[i] - x_arr[k]);
                sum2 += p / (x_arr[i] - x_arr[j]);
            }
        }
        sum1 += y_arr[i] * sum2;
    }
 
    return sum1;
}
 
//вычисление значений полуоси эллипса +
void ellipse(double a, double b, double n, vector<double>&x, vector<double>&abs_y){
    double step = abs(2*a) / (n - 1);
    double A2;
    (a > (-a)) ? A2 = a : A2 = -a;
    double x_i = -A2; //точка на оси Ox
    int k = 0;// k = [0;n-1]
    while (k <= n-1){
        x.push_back(x_i);
        if (k == 0 || k == n) {
            abs_y.push_back(0);
            
        }
        else {
            abs_y.push_back(sqrt(1 - x_i*x_i / (a*a))*b);
        }
        x_i += step; k++;
    }
};
 
//взятие интеграла: формула численного интегрирования ~~~~~
double Integral(double a, double b, double n, vector<double>x, vector<double>abs_y) {
    double A1, A2;
    if (a > -a){ A1 = b; A2 = a; }
    else{ A1 = a; A2 = b; }
    double I = 0, t0 = -sqrt(3.0 / 5.0), t1 = 0.0, t2 = sqrt(3.0 / 5.0), h = A2 / n, x0, x1, x2; int i = 0;
    while (i<n) {
        x0 = (h + 2 * i*h) / 2.0 + h*t0 / 2.0;
        x1 = (h + 2 * i*h) / 2.0 + h*t1 / 2.0;
        x2 = (h + 2 * i*h) / 2.0 + h*t2 / 2.0;
        I += h*(5 * (sqrt(1 + dL(x0, n, x, abs_y)*dL(x0, n, x, abs_y))) + 8 * (sqrt(1 + dL(x1, n, x, abs_y)*dL(x1, n, x, abs_y))) + 5 * (sqrt(1 + dL(x1, n, x, abs_y)*dL(x1, n, x, abs_y)))) / 18.0;
        i++;
    }
    return I;
}
 
int main(){
    //входные данные
    double a; double b; double n;
    cout << "a="; cin >> a;
    cout << "b="; cin >> b;
    cout << "quantity points = "; cin >> n;
    //==========================================
    vector<double>x; //табличное значение x
    vector<double>abs_y;//табличное значение f(x) (полуоси)
    vector<double>dy_dx;//табличное значение производной полуоси
    vector<double>ds;//табличное значение подыинтегральной функции
    vector<double>integral; //табличное значение интеграла
    //==========================================
    double A2;
    (a > (-a)) ? A2 = a : A2 = -a;
    double step = abs(2 * a) / (n - 1);
    //==========================================
    ellipse(a, b, n, x, abs_y);//вычисление значений полуоси
    for (double i = -A2; i <=A2; i+=step){
        dy_dx.push_back(dL(i, n, x, abs_y));//вычисление производной полуоси
    }
 
    //проверка
    
 
    int k = 0;
    cout << "\t\t" << "x";
    cout << "\t\t" << "f(x)";
    cout << "\t\t" << "abs_y";
    cout << endl;
    for (double i = -A2; i <= A2; i += step){
        cout << "\t\t" << i;
        cout << "\t\t" << setprecision(6) << f(i, a, b);
        cout << "\t\t" << setprecision(6) << abs_y[k];
        cout << endl; k++;
    }
    cout << "===============================================================================" << endl;
    k = 0;
    cout << "\t\t" << "x";
    cout << "\t\t" << "f'(x)";
    cout << "\t\t" << "dy_dx";
    cout << endl;
    for (double i = -A2; i <= A2; i += step){
        cout << "\t\t" << i;
        cout << "\t\t" << setprecision(6) << df_dx(i, a, b);
        cout << "\t\t" << setprecision(6) << dy_dx[k];
        cout << endl; k++;
    }
 
    cout << "===============================================================================" << endl;
    double S = Integral(a, b, n, x, abs_y)*2.0;//вычисление длины кривой
    cout << "\t\tcurve length = " << S << endl;//вывод ответа
    return 0;
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.11.2016, 04:22     Большая погрешность в вычислении длины кривой
Посмотрите здесь:

Погрешность и бесконечность C++
C++ Погрешность интерполяции на C++
Откуда погрешность? C++
Visual C++ Погрешность
C++ Погрешность вычислений
C++ WinAPI Погрешность длины строки GetTextExtentPoint32
C++ Погрешность в вычислениях
Большая погрешность при подсчете интеграла методом трапеций C++

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
vxg
Модератор
 Аватар для vxg
2663 / 1674 / 157
Регистрация: 13.01.2012
Сообщений: 6,251
20.11.2016, 12:42     Большая погрешность в вычислении длины кривой #2
Цитата Сообщение от almalexia1997 Посмотреть сообщение
Количество точек к сожалению только 20 программа осиливает
почему?
almalexia1997
0 / 0 / 0
Регистрация: 15.09.2014
Сообщений: 16
20.11.2016, 13:00  [ТС]     Большая погрешность в вычислении длины кривой #3
Цитата Сообщение от vxg Посмотреть сообщение
почему?
не знаю даже. видимо все дело в функции считающей производную. я кстати нашел ошибку у себя в функции интеграла:
надо исправить ее на это:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
double Integral(double a, double b, double n, vector<double>x, vector<double>abs_y) {
    double A1, A2;
    if (a > -a){ A1 = b; A2 = a; }
    else{ A1 = a; A2 = b; }
    double I = 0, t0 = -sqrt(3.0 / 5.0), t1 = 0.0, t2 = sqrt(3.0 / 5.0), h = A2 / n, x0, x1, x2; int i = 0;
    while (i<n) {
        x0 = (h + 2 * i*h) / 2.0 + h*t0 / 2.0;
        x1 = (h + 2 * i*h) / 2.0 + h*t1 / 2.0;
        x2 = (h + 2 * i*h) / 2.0 + h*t2 / 2.0;
        I += h*(5 * (sqrt(1 + dL(x0, n, x, abs_y)*dL(x0, n, x, abs_y))) + 8 * (sqrt(1 + dL(x1, n, x, abs_y)*dL(x1, n, x, abs_y))) + 5 * (sqrt(1 + dL(x2, n, x, abs_y)*dL(x2, n, x, abs_y)))) / 18.0;
        i++;
    }
    return I;
}
в квадратичной формуле Гаусса немного ошибся и два раза сосчитал в точке x1.
теперь погрешность стала нормальная, только понять не могу еще одно:
Результат интеграла я умножаю на два чтобы получить длину всего контура эллипса но в итоге я получаю длину только одной верхней полуоси так и мне приходится еще раз умножать на 2 чтобы получить длину всего уже контура.
Почему так получается никто не знает? Может у меня в математике плохо и я что-то не понимаю.
vxg
Модератор
 Аватар для vxg
2663 / 1674 / 157
Регистрация: 13.01.2012
Сообщений: 6,251
20.11.2016, 15:49     Большая погрешность в вычислении длины кривой #4
almalexia1997, к сожалению не нашел где у вас задаются пределы интегрирования, заподозрил что их вводят, может вы вводите 0 - 90 (если интегрирование в полярных координатах) поэтому считает 1/4-ю?
almalexia1997
0 / 0 / 0
Регистрация: 15.09.2014
Сообщений: 16
20.11.2016, 17:16  [ТС]     Большая погрешность в вычислении длины кривой #5
да, скорее всего вы правы, что с пределами интегрирования что-то не то. видимо он и правда находит лишь 1/4 от контура. Хотя я изначально задавал считать 1/2 от контура и потом просто умножал на 2, чтобы получить длину полуоси, он видимо считает в пределах от 0 до A2, а не от A1 до A2 как я хотел и отсюда получается что находится лишь половина от полуоси и мне приходится в конечном итоге умножать все на 4 а не на 2 как и планировалось.
Yandex
Объявления
20.11.2016, 17:16     Большая погрешность в вычислении длины кривой
Ответ Создать тему
Опции темы

Текущее время: 02:29. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru