enter image description here There is a function that calculates the value of a mathematical function by expanding it into a Taylor series. A university professor said that it was better not to divide by factorial, but to do something different. How can you optimize this function to remove factorial from the denominator?

double function(const double x) { int n=0,i; long long int factor; double eps=0.0001,F=eps+1.0, Sum=0; while(eps <= F)//Если ΠΌΠΎΠ΄ΡƒΠ»ΡŒ значСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ мСньшС Ρ‡Π΅ΠΌ eps, ΠΏΡ€Π΅ΠΊΡ€Π°Ρ‰Π°Π΅ΠΌ суммированиС { for(i=2,factor=1;i<=n;i++) factor*=i; F=(pow(-1,n) * pow(x,n)) / factor; Sum+=F; if(F<0)//Π£Π·Π½Π°Π΅ΠΌ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ "F", для сравнивания с "eps" ΠΈΠ±ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΡ‚Ρ€ΠΈΡ†Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΌ. F*=-1; n++; } return Sum; } 

    3 answers 3

    No need to calculate factorial. You can use the recurrence relation.

    Below is a sample program that uses the standard C function exp , which is declared in the header <math.h> , to compare the results. Naturally, this standard function and the corresponding title are not needed for the work of the written function.

     #include <stdio.h> #include <float.h> #include <math.h> double f(double x) { double sum = 1.0; double member = 1.0; for ( int n = 1; !(fabs( member ) < DBL_EPSILON); n++ ) { member = member * -x / n; sum += member; } return sum; } int main( void ) { for (int i = 1; i < 10; i++) { printf( "%lf %lf\n", f(i ), exp(-i)); } } 

    The output of the program to the console:

     0.367879 0.367879 0.135335 0.135335 0.049787 0.049787 0.018316 0.018316 0.006738 0.006738 0.002479 0.002479 0.000912 0.000912 0.000335 0.000335 0.000123 0.000123 

    As can be seen from the output, the results for the shown function and the standard C function of exp coincide.

      Most likely the teacher had in mind that the next member of the series for a given function can be calculated recurrently.

      Write out the members of the series:

       a_{0} = 1 a_{1} = - x/1 a_{2} = x^2/(1*2) a_{3} = -x^3/(1*2*3) a_{4} = x^4/(1*2*3*4) 

      This shows that the i -th member of the series can be calculated based on the i-1 1th member and the value of i :

       a_{i} = a_{i-1}*(-x/i), ΠΏΡ€ΠΈ i = 1,2... 

      With this approach, the inner loop can be removed.

        To make it clearer, I'll sign for math more:

        enter image description here

        enter image description here

        enter image description here

        Well, or even more :) -

        enter image description here

        So as a result, the series is considered a simple function.

         double exp_neg(double x, double eps) { double sum = 1.0, term = 1.0; for(int n = 1; term > eps || term < -eps; ++n) { sum += term *= -x/n; } return sum; } 
        • It's funny - who, judging by the minus in all the comments - problems with understanding mathematics? :) - Harry