Рейтинг:
1
CPallini
Как было предложено, используйте double
s вместо int
. Наслаждаться:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
double fact(unsigned n)
{
double result =1.0;
unsigned int i;
for (i=2; i<=n; ++i )
result *= i;
return result;
}
int main()
{
unsigned terms;
unsigned count=0;
double result = 0.0;
double angle;
printf("enter number of terms ");
scanf("%d",&terms);
printf("enter value of x ");
scanf("%lf",&angle);
while(count <= terms)
{
double sign = count & 1 ? -1.0 : 1.0;
unsigned n = 2*count+1;
result += sign*(pow(angle,(double)n)/fact(n));
count++;
}
double br = sin(angle);
printf("approximation %g, builtin function result %g, difference %5.2f%%", result, br, fabs(result-br)/br*100.0);
}
Daniel Pfeffer
Это будет крайне неточно даже для малых значений X. Вы должны, по крайней мере, использовать правило Хорнера для оценки многочлена. Смотрите мое решение для других соображений.
CPallini
Вы действительно пробовали это сделать?
Daniel Pfeffer
1. pow(x, y) _may_ имеет оптимизацию для случая интеграла y, но это не гарантируется. В противном случае он вычисляет exp(y*log(x)).
2. Даже если оптимизация существует, вы будете иметь между lg(n) и 2*lg(n) умножениями для расчета мощности _each_ со всеми связанными ошибками и дополнительными вычислениями.
3. Правило Хорнера - f(x) = (...((a[n]*x + a[n-1])*x + a[n-2])*x ...) +a[0] использует n умножений и n сложений для выполнения вычисления, которое является одновременно более быстрым и точным.
4. Современный компилятор C или C++ предоставляет фма(). Использование этого метода сводит вычисление к n операциям fma() с соответствующим повышением точности.
5. Также нет необходимости пересчитывать факториал на каждом этапе. Он может быть рассчитан "бесплатно", установив a[2*k+1] = +/-1.0/(2*k*(2*k+1)), a[1] = 1,0.
6. предполагая, что x даже умеренно велик (скажем, 100.0), ваш метод переполнится задолго до того, как вы достигнете приемлемой точности - вам понадобится по крайней мере 150 элементов (n = 300) и 300! переполнится задолго до того, как вы достигнете этого.
CPallini
Что такое "Х", которое вы написали в точке (6)?
Кстати, вы мне не ответили.
Daniel Pfeffer
x-это аргумент для вашего вычисления sin ().
Нет, я не запускал код; достаточно просто посмотреть, как вы реализовали степенной ряд. Были ли какие-либо мои комментарии по поводу кода неверными? :)
CPallini
Ваш подход кажется мне неправильным. ОП пытался реализовать серию Тейлора, и я помогал в этой самой теме.
Я думаю, что ваши замечания могут быть полезны для числовых экспертов. Если мне когда-нибудь понадобится грех(x) Я использую, ну встроенный грех(x). И нет, я обычно не предоставляю 100 в качестве аргумента для sin(x). Вы действительно хотите сказать, что 100-это небольшое значение x? Ерунда.
Daniel Pfeffer
При моделировании многих физических систем вы вычисляете sin(omega*t), где omega-частота, а t-время. Эти цифры могут быть довольно большими - намного больше 100,0.
Что касается вашего второго пункта, то мы должны согласиться не согласиться. :)
Рейтинг:
0
Daniel Pfeffer
Использование бесконечного ряда для вычисления функции займет много времени. Прежде чем сделать это, спросите себя:
1. Является ли функция периодической? Если да, то сведите аргумент к одному периоду.
2. Это чет или нечет (Ф(Х) == -ф(-х) или F(Х) == ф(-х) )? Если это так, запишите нечетную функцию, например x*F(x^2), и четную функцию, например G(x^2).
3. Существуют ли какие-либо другие атрибуты функции, которые могут помочь?
Как только вы это сделаете, вы обнаружите, что для получения требуемой точности требуется только конечное число элементов.
Удачи вам!