Как создать синусоидальную функцию в c

#c #math

#c #математика

Вопрос:

Я знаю, что в sin есть math.h функция, но я хочу создать эту функцию самостоятельно, просто для развлечения. Я создал sin функцию, основанную на расширении функции синуса по Маклуарину. введите описание изображения здесь

Я написал степенную функцию и факториальную функцию, они корректно работают с main , но они не работают в sin функции.

Вот мой код:

 int main()
{
    int i;
    double y;
    printf("nnPlease enter a value to find corresponding sin valuen");
    scanf("%d",amp;i);
    y=sin(i);
    printf("nYour value isn %f",y);
    return 0;
}
    
double sin(int z)
{
    int i=1;
    double value,val2,val3,sum=0;
    for(i=1;i<33;i =2)
    {
        val2=power(z,i);
        val3=factorial(i);
        value=val2/val3;
        if(((i-1)/2)%2!=0){
            sum=sum-value;    //((power(x,i))/factorial(i));
        }else
        {
            sum=sum value;
        }
    }
    printf("n%fn",sum);
    return sum;
}

int factorial(int x)
{
    int i,sum=1;
    for(i=1;i<=x;i  )
    {
        sum = sum*i;
    }
    return sum;
}

int power(int x,int y)
{
    unsigned long long int i,sum=1;
    for(i=1;i<=y;i  )
    {
        sum=sum*x;
    }
    return sum;
}
  

Комментарии:

1. Помимо переполнений, использование целых чисел приведет к усечению десятичных знаков. О, и вы объявляете функции перед их вызовом? У вас есть прототипы функций где-нибудь над main функцией?

2. какова цель этого условия if if(((i-1)/2)%2!=0) ?

3. @ARBY это для - значения в последовательности типа sum-x ^ 3/3!

Ответ №1:

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

Также вы используете int s в качестве возвращаемых значений из factorial() и power() , которые будут вызывать переполнения. Если у вас 32-битная машина, даже присвоение 2 вашей формуле приведет к переполнению, поскольку int может доходить только до 2 ^ 31-1, а вы пытаетесь получить 2 ^ 33.

Также, если ваш компилятор не жалуется на то, что вы возвращаете unsigned long long int из функции, которая имеет int в качестве возвращаемого типа, пожалуйста, увеличьте уровень предупреждения.

Ответ №2:

int factorial() переполняется довольно быстро. 13! не вписывается в 32-разрядное целое число. 21! не вписывается в 64-разрядное целое число.

int power() кажется совершенно неправильным. Почему вы ожидаете, что аргумент x будет int ? Кстати, она также быстро переполняется.

(Почти) правильный способ вычисления ряда Маклорена — это выразить следующий член из предыдущего:

     term = (-1) * term * (x*x) / ((n 1)*(n 2));
    sum  = term;
    n  = 2;
  

Это должно работать, но может привести к числовой нестабильности с большими x . Расписание Хорнера — это окончательный ответ.

Ответ №3:

Если вы посмотрите на стандартные математические библиотеки, такие как fdlibm, все они выполняют сокращение аргументов. Серия Маклуарина лучше всего работает при малых значениях x . Таким образом, для больших x вы хотите поместить x в небольшой диапазон. Работаем в радианах, если мы можем найти y между -pi / 2 и pi / 2 такими, что x = y 2 k pi. Или x = pi — y 2 k pi.

Это поможет поместить y в небольшой диапазон и означает, что вам потребуется меньше членов ряда для вычисления.

Ответ №4:

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

Вы можете попробовать объединить вычисления так, чтобы у вас были multiplication и a divide в каждом цикле.

Вот так:

 #include <stdio.h>

// This function returns the contribution from the k'th element
double kth_contribution(double x, int k)
{
    int i;
    int s = -1.0;
    double d = 1.0;
    if (k < 0) return 0;
    if (k == 1) return x;
    if (k % 2 == 0) return 0;
    if ((k-1) % 4 == 0) s = 1.0;

    for (i=1; i<=k;   i)
    {
        d = d * x / i;
    }
    d = s * d;
    return d;
}

int main(void) {
    int k;
    int x = 1.0;
    for (k=0; k<33;   k)
    {
        printf("k=%d: %0.80fn", k, kth_contribution(1.0, k));
    }
    return 0;
}
  

Вывод:

 k=0: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=1: 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=2: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=3: -0.16666666666666665741480812812369549646973609924316406250000000000000000000000000
k=4: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=5: 0.00833333333333333321768510160154619370587170124053955078125000000000000000000000
k=6: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=7: -0.00019841269841269841252631711547849135968135669827461242675781250000000000000000
k=8: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=9: 0.00000275573192239858925109505932704578867742384318262338638305664062500000000000
k=10: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=11: -0.00000002505210838544172022386617932135366437762513669440522789955139160156250000
k=12: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=13: 0.00000000016059043836821615925802332523156679827680548555690620560199022293090820
k=14: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=15: -0.00000000000076471637318198174152558028953378813433183758263567142421379685401917
k=16: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000
k=17: 0.00000000000000281145725434552099254097088490189675684814327692728763707918915316

....
  

Теперь вам просто нужно сложить все вклады вместе.