С Новым годом! Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/34: Рейтинг темы: голосов - 34, средняя оценка - 4.88
0 / 0 / 0
Регистрация: 13.09.2020
Сообщений: 7
1

Тангенс угла через ряд Тейлора

24.09.2020, 19:47. Показов 7043. Ответов 6

Author24 — интернет-сервис помощи студентам
Здравствуйте, у меня работает данная программа для нахождения маленьких углов. Но, например при нахождении угла в 6,28 радиан выдаёт ошибку. Как решить данную проблему?
(Возможно надо увеличить кол-во итераций, но тогда в значениях выдаётся -nan(ind).)

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
include<stdio.h>
#include<locale.h>
 
int main()
{
    setlocale(LC_ALL, "Rus");
    int n = 10, i = 1;
    long int fakt = 1;
    double x, st, y1 = 0, y2 = 1, znak = 1;
    printf("Введите угол в радианах ");
    scanf_s("%lf", &x);
    st = x;
    if (x == 6.28)
        printf("tg = 0");
    else if (x == 1.57)
        printf("Невозможно");
    else
    {
        do //нахождение sin
        {
            fakt = 1;
            for (int j = 1; j <= i * 2 - 1; j++)
                fakt *= j;
            y1 += znak * (st / fakt);
            i++;
            st *= x * x;
            znak *= -1;
        } while (i < n);
        printf("sin = %lf\n", y1);
        st = x * x;
        i = 1;
        znak = -1;
        do // cos
        {
            fakt = 1;
            for (int j = 1; j <= 2*i; j++)
                fakt *= j;
            y2 += znak * (st / fakt);
            i++;
            st *= x * x;
            znak *= -1;
        } while (i < n);
        printf("cos = %lf\n", y2);
        printf("tg = %lf", y1 / y2);
    }
    return 0;
}
0
Лучшие ответы (1)
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Блог
24.09.2020, 19:47
Ответы с готовыми решениями:

Вычисление значения синуса угла разложением в ряд Тейлора
Здравствуйте. Задача: написать код, который вводит угол (градусы или радианы) и с помощью ряда...

Косинус через ряд Тейлора
Вот надо написать функцию косинуса через тейлора без математических библиотек. Но так как я еще...

Косинус через ряд Тейлора
Собсно, все на пикче. Хелп плз. Задачи на ряд Тейлора уже смотрел на форуме, но как вывести...

Вычисление экспоненты через ряд Тейлора
Сама формула имеет вид : {e}^{x}=1+\frac{x}{1!}+\frac{{x}^{2}}{2!}+\frac{{x}^{3}}{3!}+... Сколько...

6
2129 / 1212 / 503
Регистрация: 11.10.2018
Сообщений: 6,120
24.09.2020, 20:15 2
Цитата Сообщение от OpoPo Посмотреть сообщение
C++
1
if(x == 6.28)
- это не сработает для дробных.
Насколько я понимаю есть ряды где x должен быть x < 1, иначе ряд не сработает. Возможно у Вас этот ряд.

Добавлено через 14 минут
Дак для тангенса, же вроде свой ряд есть? Зачем sin и cos считать?
0
Модератор
Эксперт по электронике
8543 / 4395 / 1651
Регистрация: 01.02.2015
Сообщений: 13,659
Записей в блоге: 9
24.09.2020, 20:55 3
OpoPo, замените вычисления, чтобы обойтись без непосредственного вычисления факториала.

Покажу для sin(x), а для cos(x) сделаете по аналогии

https://www.cyberforum.ru/cgi-bin/latex.cgi?\sin x=\sum_{n=0}^{\infty}a_n
где
https://www.cyberforum.ru/cgi-bin/latex.cgi?a_n=(-1)^n\cdot \frac{x^{2n+1}}{(2n+1)!}
предыдущий член ряда
https://www.cyberforum.ru/cgi-bin/latex.cgi?a_{n-1}=(-1)^{n-1}\cdot \frac{x^{2n-1}}{(2n-1)!}
их соотношение
https://www.cyberforum.ru/cgi-bin/latex.cgi?\frac{a_n}{a_{n-1}}=- \frac{x^{2}}{(2n)\cdot (2n+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
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#define EPS 1e-5
int main()
{
 
    double x;
 
    x=6.28;
 
    int n=0;
    double s,a;
    s=a=x;
    do
    {
        n++;
        a *=-x*x/(2.0*n)/(2.0*n+1.0);
        s+=a;
    }
    while((n<100)&&(fabs(a)>EPS));  //тут я что-то намудрил, но пойдёт
 
    printf("sin: Taylor=%f, builtin=%f\n",s, sin(x));
 
    return 0;
}
Для вычисления разложения непосредственно тангенса в ряд потребуется ещё и вычисление чисел Бернулли, что в общем-то не совсем тривиальная задача, хотя и для неё существуют быстрые алгоритмы.
0
0 / 0 / 0
Регистрация: 13.09.2020
Сообщений: 7
24.09.2020, 22:09  [ТС] 4
Мне нельзя использовать библиотеку math.

Добавлено через 1 минуту
Я не понимаю последовательность для тангенса. Там какие-то странные преобразования.
0
Модератор
Эксперт по электронике
8543 / 4395 / 1651
Регистрация: 01.02.2015
Сообщений: 13,659
Записей в блоге: 9
24.09.2020, 22:16 5
Для вычислений чисел Бернулли видел примерно с десяток алгоритмов.
В часности
Функция подсчета чисел Бернулли

Перенос на C не займёт много времени. Но, вероятно это и не требуется.
Вычисляйте sin и cos по реккурентной формуле, сравнивайте cos с нулём и получайте тангенс.
0
Модератор
Эксперт функциональных языков программированияЭксперт Python
37416 / 20788 / 4278
Регистрация: 12.02.2012
Сообщений: 34,199
Записей в блоге: 14
25.09.2020, 08:50 6
Даже правильный код начнет давать большую (огромную!) погрешность при больших значениях аргумента. Это принципиальный момент - проблема чисел с плавающей точкой.
0
Модератор
Эксперт по электронике
8543 / 4395 / 1651
Регистрация: 01.02.2015
Сообщений: 13,659
Записей в блоге: 9
25.09.2020, 10:42 7
Лучший ответ Сообщение было отмечено OpoPo как решение

Решение

Мне кажется, что основная ошибка - непосредственное вычисление факториала. В итоге вычисляется 20!, что переполняет разрядность. При малом значении аргумента x это как-то компенсируется.

Для правильного вычисления нужно вычислять по реккурентной формуле.

Но, ТС, похоже совсем не умеет программировать и код где-то нашёл, потому, что мои пояснения о реккурентных вычислениях он отмёл фразой
Цитата Сообщение от OpoPo Посмотреть сообщение
Мне нельзя использовать библиотеку math.
т.е. даже без попытки разобраться.

Добавлено через 34 минуты
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
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#define EPS 1e-5
int main()
{
 
    double x;
    double sin_x, cos_x, tg_x;
 
    x=30.456;
 
    //sin(x)
    int n=0;
    double s,a;
    s=a=x;
    do
    {
        n++;
        a *=-x*x/(2.0*n)/(2.0*n+1.0);
        s+=a;
    }
    while((n<100)&&(fabs(a)>EPS));
 
    printf("sin: Taylor  = %f\n     built-in= %f\n",s, sin(x));
    sin_x=s;
 
    //cos(x)
    n=0;
    s=a=1;
    do
    {
        n++;
        a *= -x*x/(2.0*n-1.0)/(2.0*n);
        s += a;
    }
    while((n<100)&&(fabs(a)>EPS));
 
    printf("cos: Taylor  = %f\n     built-in= %f\n",s, cos(x));
    cos_x=s;
 
    //tg(x)
    tg_x=sin_x/cos_x;
    printf("tg:  Taylor  = %f\n     built-in= %f\n",tg_x, tan(x));
 
    return 0;
}
хотя и здесь проблема вычислений при больших значениях аргумента остаётся, хотя и перенесена дальше, чем 6,28. Проблема возникает из-за того, что показательная функция x2n на начальном этапе растёт быстрее факториала (2n)!, что приводит к переполнению разрядной сетки.

Выходов может быть несколько:
1) уменьшить x до приемлемых значений вычитанием https://www.cyberforum.ru/cgi-bin/latex.cgi?k\cdot \pi
2) использовать функции двойного (тройного) аргумента для вычисления sin и cos, т.е. x делится на 2k до достижения приемлемых значений, а потом последовательно вычислять функции удвоением аргумента до достижения значения x.

Добавлено через 57 минут
Процедура my_sincos. Делением на 2 приводим аргумент к значению не превосходящему 1,0 - получим условный z=x/2k. При этом подсчитываем количество таких делений - k.
Для уменьшенного аргумента без проблем вычисляем значения sin(z) и cos(z).
Потом по формулам удвоения аргумента в цикле k раз вычисляем sin(2z) и cos(2z) и окончательно получаем sin(x) и cos(x).
Чтобы не вводить лишние переменные, вместо z используем x, тем боле, что после вычисления начального приближения через ряд Тейлора, ни значение x, ни значение z уже не требуется.

Продемонстрирую подход со значением x=300, при котором непосредственное вычисление при помощи ряда Тейлора переполняет разрядную сетку.
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
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
 
#define EPS 1e-8
#define MAX_N 10000
 
double t_sin(double x)
{
    int n=0;
    double s,a;
    s=a=x;
    do
    {
        n++;
        a *=-x*x/(2.0*n)/(2.0*n+1.0);
        s+=a;
    }
    while((n<MAX_N)&&(fabs(a)>EPS));
    return s;
}
 
double t_cos(double x)
{
    int n=0;
    double s,a;
    s=a=1;
    do
    {
        n++;
        a *= -x*x/(2.0*n-1.0)/(2.0*n);
        s += a;
    }
    while((n<MAX_N)&&(fabs(a)>EPS));
    return s;
}
 
void my_sincos(double x, double *sin_r, double *cos_r)
{
    //приводим аргумент к приемлемым значениям для вычисления
    int k=0;
    while(fabs(x)>1.0) x /=2.0, k++;
    //вычисляем первое приближение через ряд Тейлора
    double sin_x=t_sin(x);
    double cos_x=t_cos(x);
    //вычисляем для исходного аргумента
    for(; k>0; k--)
    {
        double sin_2x=2*sin_x*cos_x;
        double cos_2x=1-2*sin_x*sin_x;
 
        sin_x=sin_2x;
        cos_x=cos_2x;
    }
    *sin_r=sin_x;
    *cos_r=cos_x;
    return;
}
 
int main()
{
 
    double x;
    double sin_x, cos_x, tg_x;
 
    x=300.456;
 
    //sin(x)
    sin_x=t_sin(x);
    printf("sin: Taylor  = %f\n     built-in= %f\n",sin_x, sin(x));
 
    //cos(x)
    cos_x=t_cos(x);
    printf("cos: Taylor  = %f\n     built-in= %f\n",cos_x, cos(x));
 
    //tg(x)
    tg_x=sin_x/cos_x;
    printf("tg:  Taylor  = %f\n     built-in= %f\n",tg_x, tan(x));
 
    my_sincos(x,&sin_x,&cos_x);
    printf("sin: My      = %f\n     built-in= %f\n",sin_x, sin(x));
    printf("cos: My      = %f\n     built-in= %f\n",cos_x, cos(x));
 
    return 0;
}
2
25.09.2020, 10:42
BasicMan
Эксперт
19315 / 2622 / 84
Регистрация: 17.02.2009
Сообщений: 10,364
Блог
25.09.2020, 10:42
Помогаю со студенческими работами здесь

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

Найти в треугольнике тангенс угла альфа и длину биссектрис
Нужно найти в треугольнику тангенс кута альфа и длину бисектрисы бета

Вычисление гиперболического косинуса через разложение в ряд Тейлора с помощью рекурсивной процедуры
Мне нужно написать рекурсию на примере Ряда Тэйлора на гиперболический косинус , вообще не...

Тангенс через разложение в ряд Тейлора
Подскажите пожалуйста как в C# посчитать тангенс через разложение в ряд Тейлора. В примере...

Тангенс угла в прямоугольном треугольнике зная тангенс другого угла
Пускай имеем прямоугольный треугольник. Знаем тангенс одного из не прямых углов. Как найти тангенс...

Если разложить тангенс в ряд Тейлора, будет ли он расходиться или сходиться?
Если разложить тангенс в ряд Тейлора, то он будет расходиться или сходится? (при больше 100...


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

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