Вычислить sin (x) и cos (x) с помощью серии Тейлора в C [дубликат]

Тип raw - это отсутствие параметра типа при использовании родового типа.

Необработанный тип не должен использоваться, потому что это может привести к ошибкам во время выполнения, например, вставить double в то, что должно было быть Set из int s.

Set set = new HashSet();
set.add(3.45); //ok

При извлечении материала из Set вы надеваете Не знаю, что выйдет. Предположим, что вы ожидаете, что это все int s, вы отбрасываете его на Integer; исключение во время выполнения, когда приходит double 3.45.

С параметром типа , добавленным к вашему Set, вы сразу же получите ошибку компиляции. Эта превентивная ошибка позволяет устранить проблему, прежде чем что-то взорвется во время работы (таким образом, сэкономив время и усилия).

Set<Integer> set = new HashSet<Integer>();
set.add(3.45); //NOT ok.
1
задан Edward 26 February 2014 в 22:41
поделиться

6 ответов

Одна вещь, которую я вижу, заключается в том, что ваш цикл for внутри main работает только через 2 настоящие итерации, один раз для i == 0 и снова для i == 1.

Для расширения taylor для работы довольно эффективно, его нужно запускать через более последовательности (больше итераций цикла).

другое, что я вижу, это то, что ваш знаменатель является n! а не (2 * n)!

Для эффективности я мог бы также реализовать факториальную процедуру следующим образом:

unsigned int factorial(int n){
    unsigned int product = 1;

    for(int I = 1; I <= n; I++) product *= I;

    return product;
}

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

float factorial(int n){
    float product = 1;

    for(int I = 1; I <= n; I++) product *= (float)I;

    return product;
}

Также я должен отметить, почему я заявляю, что выполняю факториал таким образом. В общем случае конструкция цикла будет более эффективной, чем ее рекурсивная копия. Ваша текущая реализация рекурсивна, и, таким образом, реализация, которую я предоставляю, ДОЛЖНА быть более эффективной как от производительности, так и от использования памяти.

3
ответ дан trumpetlicks 20 August 2018 в 16:33
поделиться
  • 1
    Проблема с вашим пересмотренным факториалом заключается в том, что он использует целочисленные вычисления вместо float, и вы не можете хранить более 12! или около того в int. – Jonathan Leffler 26 February 2014 в 21:25
  • 2
    @JonathanLeffler На самом деле это не проблема, так как factorial является единственной математической функцией INTEGER. С плавающей точкой из факториала больше 12! это просто мусор (математически). Однако в этом конкретном случае я вижу вашу точку зрения, что, возможно, ОЦЕНКА с плавающей точкой может быть достаточно хорошей для вычисления косинуса. Я уточню свой ответ! – trumpetlicks 26 February 2014 в 21:31
  • 3
    В частности, проблема заключается в том, что «целочисленная аппроксимация факториалу» для значений, больших 12, является (математически) мусором, потому что математическое значение слишком велико, чтобы вписаться в 32-битное целое число. Вы отменили неопределенное поведение, используя unsigned int, но это оставляет вам по модулю 2 ^ 32 арифметики значение факториала. – Jonathan Leffler 26 February 2014 в 21:38
  • 4
    – trumpetlicks 26 February 2014 в 22:24
  • 5
    Я не понимаю, зачем вычислять факториал для каждого элемента в серии. кажется довольно расточительным. Также будет переполнение, когда это можно легко преодолеть. – Ed Heal 26 February 2014 в 23:22

Почему вы вычисляете мощность и т. д. для каждого элемента в серии? Также необходимо сохранить числа в подходящем диапазоне для типов данных

, т.е. для cos

bool neg_sign = false;
float total = 1.0f;
float current = 1.0f;
for (int i = 0; i < length_of_series; ++i) {
    neg_sign = !neg_sign;
    current = current * (x / ((2 * i) + 1)) * (x / (( 2 * i) + 2));
    total += neg_sign ? -current : current;
}

EDIT

См. http://codepad.org/swDIh8P5

1
ответ дан Ed Heal 20 August 2018 в 16:33
поделиться
  • 1
    sign = !sign, вы имели в виду neg_sign? – Mhd.Tahawi 26 February 2014 в 21:39
  • 2
    @ Mhd.Tahawi - да - просто исправлял это – Ed Heal 26 February 2014 в 21:40
  • 3
    Это часть задания, мне нужно было отображать значения «x», как в моей собственной косинусной функции, так и в библиотеке math.h и сравнивать результаты. Цель состоит в том, чтобы выяснить, как писать и создавать необходимые данные, чтобы иметь возможность строить. То, что вы сделали, было более продвинутым, чем мой нынешний уровень мастерства, но я надеюсь скоро это понять (мой опыт включает около 4-6 недель, я был брошен в огонь с этим классом хахаха). Спасибо за ваш вклад! – Edward 27 February 2014 в 01:03
  • 4
    @Edward - я просто применил некоторую алгебру к исходному суммированию. Как вы делаете n-й факториал из (n-2) факториала? Как вы делаете x ^ n из x ^ (n-2)? Конечно, вы можете понять, что из-за математики. Затем просто немного перегруппировки, чтобы сохранить умножения одинаковой величины, чтобы уменьшить ошибки – Ed Heal 27 February 2014 в 01:11

Рассматривая затраты на вычисления, вам нужно прекратить вычислять серию в точке. Чем больше вы идете, тем более точным будет результат, но чем больше ваша программа проводит время. Как насчет этой простой программы:

#include <stdio.h>
#include <math.h>

#define ITERATIONS 10 //control how far you go

float factorial(int n){
    if (n==0)
        return 1;
    else
        return n*factorial(n-1);
}

int main (){
    float n;
    float sum=0;
    printf("Enter desired float: ");
    scanf("%f", &n);

    int c, i;
    for (i=0; i<=ITERATIONS; i++) {
        c = (i%2)==0? 1 : -1;
        sum = sum + (c*pow(n,2*i+1))/(factorial(2*i+1));
    }

    printf("The value is %f\n", sum);
    return 0;
}
2
ответ дан Farzad 20 August 2018 в 16:33
поделиться
  • 1
    Это то, что помогло мне больше всего, спасибо! – Edward 26 February 2014 в 22:42
  • 2
    Но вы приняли другой ответ: D – Farzad 26 February 2014 в 22:45
  • 3
    Я использовал оба ответа, чтобы понять это, ваш помог мне увидеть ошибку ввода, в то время как другой сказал больше о концепции и помог мне понять, что мой мыслительный процесс был неправильным. Я могу выбрать только один, но я все еще проголосовал за ваш ответ. (Я бы хотел проверить на самом деле). Я сожалею, хотя, если я обидел вас, но благодарен за то, что вы наткнулись на мою просьбу о помощи. – Edward 26 February 2014 в 23:12
  • 4
    Не беспокойтесь, мой друг;) Мне тоже нравится другой ответ. Желаю вам успеха в кодировании C. – Farzad 26 February 2014 в 23:15

1.) Вы только умножаете, даже no.s в факториальной функции return 2*n*factorial(n-1); будут давать только четные значения. Вместо этого вы можете заменить n на 2n здесь sum = sum + (pow(-1,i)*pow(n,2*i))/(factorial(2n));. Это даст правильный (2n!). 2.) Проверьте, нет ли итераций for (i=0; i<=1; i++), это приведет к двойному запуску вашего цикла. Попробуйте больше нет. итераций для более точного ответа.

1
ответ дан Imdad 20 August 2018 в 16:33
поделиться

Ваша функция factorial() фактически вычисляет 2n.n! , что, вероятно, не то, что вы имели в виду. Чтобы вычислить (2n)! , вам нужно удалить 2* из тела функции и вызвать factorial(2*n).

0
ответ дан Jonathan Leffler 20 August 2018 в 16:33
поделиться
#include<stdio.h>
# define PRECISION 10                      /*the number of terms to be processed*/
main()
{
                 float x,term=1,s=1.0;
                 int i,a=2;
                 scanf("%f",&x);
                 x=x*x;
                 for(i=1;i<PRECISION;i++)
                 {
                           term=-term*x/(a*(a-1));
                           s+=term;
                           a+=2;
                 }
                 printf("result=%f",s);
}
1
ответ дан lokesh5790 20 August 2018 в 16:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: