'Why is C++ not changing my code's numbers' condition according to pow (-1,i)?

I have C++ code here:

 #include <iostream>
 #include <cmath>
 #include <time.h>
 using namespace std;
    
 int main()
 {
    
        double n,x;
        cin>>n>>x;
        double b=1,c=0.0;
        for (int i=1;i<=n;i++){
            x=pow(x,i);
            x=x*pow((-1),(i+1));
            cout<<x<<endl;
            b=i;
            c=c+x/b;
    
        }
        cout<<c<<endl;
    
        return 0;
 }

I am creating this to calculate x^1-x^2/2+x^3/3-.....+(-1)^(n-1)*(x^n)/n. The user inputs n. The problem appears to be in this line: x=x*pow((-1),(i+1));.



Solution 1:[1]

I am creating this to calculate x^1 - x^2/2 + x^3/3 - ... + (-1)^(n-1)*(x^n)/n.

That seems to be the Maclaurin series of ln(1 + x), but it's not what the posted code evaluates, though:

for (int i=1;i<=n;i++)
{
   x = pow(x,i);
   //      ^     This is updated at each iteration! It should be const.  

   x = x * pow((-1),(i+1));
   //      ^^^^^^^^^^^^^^^  Please don't (see later).

   b=i;
   c=c+x/b;
   //    ^  Okish, but why not use i directly?
}

At the very least, a variable different from x should be introduced to store the results of the powers.

The use of pow((-1),(i+1)) to generate the simple sequence {1, -1, 1, -1, ...} is also questionable, if not prone to rounding errors. I'll show two different ways to accomplish the same task.

// Evaluates the Mclaurin series of ln(1 + x) using n terms.

// Noting that (e.g. with n == 4):
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
// p(4) = x - x*x/2 + x*x*x/3 - x*x*x*x/4
// p(4) = k(1) -x*k(1)/2 + x*x*x/3 - x*x*x*x/4      k(1) = x 
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 - x*x*x*x/4      k(2) = -x*k(1)
// p(4) = k(1) -x*k(1)/2 -x*k(2)/3 -x*k(3)/4        k(3) = -x*k(2)
  
// Preconditions: n >= 1  and  -1 < x <= 1
double fn(int n, double x)
{
    double k{ x };
    double sum{ x };
    for (int i{ 2 }; i <= n; ++i)
    {
        k *= -x;
        sum += k / i;
    }
    return sum;
}

Note that, in the interval of convergence, abs(k / i) tends to zero, while outside it grows. Eventually, due to the limited precision of floating-point types like double, sum += k/i won't change the value of sum.

Another approach may be based on Horner's rule.

// Evaluates the Mclaurin series of ln(1 + x) using n terms.

// Applying Horner's rule:
// p(4) = x -x^2 / 2 + x^3 / 3 - x^4 / 4
//      = x*(1 + x*(-1/2 + x*(1/3 + x*(-1/4))))
//      = x*(1 + x*(-1/2 + x*( 1/3 + x*k(4) )))   k(4) = 1/4
//      = x*(1 + x*( -1/2 + x*k(3) ))             k(3) = 1/3 + x*k(4) 
//      = x*( 1 + x*k(2) )                        k(2) = -1/2 + x*k(3)
//      = x * k(1)                                k(1) = 1 + x*k(2)  

// Preconditions: n >= 1 and -1 < x <= 1
double fn(int n, double x)
{
    double sign{ n % 2 == 0? -1.0 : 1.0 };
    double k{ sign / n };
    while ( --n > 0 )
    {
        sign = -sign;
        k = sign / n + x * k;
    }
    return k * x;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bob__