Этот код серии Тейлора не работает для n = 1 или чего-либо другого, кроме 0. Почему?

Прежде всего, позвольте мне сказать вам, я изучаю программирование.

Сегодня я попытался найти приблизительное значение косинуса, используя ряд Тейлора. Когда я ставлю n=0, мой код дает правильный результат 1. Но когда я ставлю n=1 или что-то еще, мой код не дает правильного результата.

Я не могу понять, где проблема. Кто-нибудь может помочь?

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main(int argc, char *argv[])
{
    float xnot = atof(argv[1]);
    float n = atof(argv[2]);
    float cosine = cos(xnot*(3.14159265/180));
    float result;
    printf("%.4f\n", cosine);
    float min;


    float d, c, b;
    c = 1;
    d = 2 * n; 
    for(b = 1; b <= d; b++){
        c = c * b; /*value of the factorial is in c*/
    }
    c = c;
    float power;
    power = pow((-1), n);
    xnot = pow(xnot, 2*n);


    for(min = 0; min <= n; min++)
    {

        result += ((power * xnot) / c);
    }
    printf("%.4f", result);
}

person ProgrammingEnthusiast    schedule 20.11.2017    source источник
comment
Пожалуйста, вставьте свой код, а не изображение вашего кода.   -  person AntonH    schedule 21.11.2017
comment
Ok. Я попробую.   -  person ProgrammingEnthusiast    schedule 21.11.2017
comment
ты учишься в университете? наверное тебе стоит пойти в ТП   -  person Jason Hu    schedule 21.11.2017
comment
Что такое ТА?? @HuStmpHrrr   -  person ProgrammingEnthusiast    schedule 21.11.2017
comment
ассистент преподавателя. ты первый год? найдется куча людей, обязанных помочь вам в таких мелочах.   -  person Jason Hu    schedule 21.11.2017
comment
TA = Ассистент преподавателя. Иногда его называют CA = Classroom Assistant. Ученик старшего класса, который помогает профессорам, помогая студентам, оценивает домашние задания, работает в офисе, иногда преподает в классах младших классов.   -  person Bob Jarvis - Reinstate Monica    schedule 21.11.2017
comment
Я на первом курсе. Но можно ли найти какое-либо решение этой проблемы? @HuStmpHrrr   -  person ProgrammingEnthusiast    schedule 21.11.2017
comment
тут многие могут. я хочу сказать, что размещение каждого подробного вопроса на этом сайте в значительной степени вам не поможет. правильно обученный ассистент может разобраться с этим за 5 минут лично, и вы можете перейти к следующему вопросу. сколько времени вы уже потратили на этот вопрос?   -  person Jason Hu    schedule 21.11.2017
comment
Вы делите каждый член на один и тот же факториал. Вот реализация Тейлора, но она для синуса, так что это не распродажа.   -  person Weather Vane    schedule 21.11.2017
comment
Я все делаю сам. И так ровно 2 часа!! Неплохо!! @HuStmpHrrr Лол.   -  person ProgrammingEnthusiast    schedule 21.11.2017


Ответы (3)


Вам нужно переделать все вычисления внутри цикла for. Сохраняя как можно больше исходного кода, это может быть что-то вроде:

int n = atoi(argv[2]);  // n is an integer
...
...
float result = 1;  // The first term (n=0) gives 1

for(int i = 1; i <= n; i++)   // Start the loop from 1
{
    float d, c, b;
    c = 1;
    d = 2 * i;     // Use i instead of n
    for(b = 1; b <= d; b++){
        c = c * b; /*value of the factorial is in c*/
    }
    float power;
    power = pow((-1), i);    // Use i instead of n
    xnot = pow(xnot, 2*i);   // Use i instead of n

    result += ((power * xnot) / c);
}

Код можно оптимизировать — как по производительности, так и по точности — но, как уже говорилось, я старался сохранить его как можно ближе к исходному коду.

person 4386427    schedule 20.11.2017

При реализации ряда Тейлора вы должны пересчитать значение терминов для каждого значения «n». Здесь похоже, что вы вычислили значение -1^n (как xnot) для максимального значения n, а затем просто умножаете на это значение для каждой итерации. Это неверно. То же самое для значений x^2n / (2n)! - вы должны пересчитать это для каждого значения n по мере его увеличения, а затем суммировать значения.

Удачи.

person Bob Jarvis - Reinstate Monica    schedule 20.11.2017
comment
Спасибо за помощь. - person ProgrammingEnthusiast; 21.11.2017

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

#define TSLIM 20    /* Series Limit (no. of terms) */
...
/** cos with taylor series expansion to n = TSLIM
 *  (no function reliance, quadrants handled)
 */
double cosenfq (const double deg)
{
    double fp = deg - (int64_t)deg, /* save fractional part of deg */
        qdeg = (int64_t)deg % 360,  /* get equivalent 0-359 deg angle */
        rad, cose_deg = 1.0;        /* radians, cose_deg */
    int pos_quad = 1,               /* positive quadrant flag 1,4  */
        sign = -1;                  /* taylor series term sign */

    qdeg += fp;                     /* add fractional part back to angle */

    /* get equivalent 0-90 degree angle, set pos_quad flag */
    if (90 < qdeg && qdeg <= 180) {         /* in 2nd quadrant */
        qdeg = 180 - qdeg;
        pos_quad = 0;
    }
    else if (180 < qdeg && qdeg <= 270) {   /* in 3rd quadrant */
        qdeg = qdeg - 180;
        pos_quad = 0;
    }
    else if (270 < qdeg && qdeg <= 360)     /* in 4th quadrant */
        qdeg = 360 - qdeg;

    rad = qdeg * M_PI / 180.0;      /* convert to radians */

    /* compute Taylor-Series expansion for sine for TSLIM / 2 terms */
    for (int n = 2; n < TSLIM; n += 2, sign *= -1) {
        double p = rad;
        uint64_t f = n;

        for (int i = 1; i < n; i++)     /* pow */
            p *= rad;

        for (int i = 1; i < n; i++)     /* nfact */
            f *= i;

        cose_deg += sign * p / f;       /* Taylor-series term */
    }

    return pos_quad ? cose_deg : -cose_deg;
}

При ограничении в 20 сроков максимальная ошибка составляет примерно 1.2E-15 (по сравнению с math.h cos())

person David C. Rankin    schedule 20.11.2017