c++loopstrigonometrytaylor-series

C++ Endless loop with function sin x problem


I am practicing for my final exam and professor sent us a last year's copy and in it, there is this assignment: Image of assignment

I made a code for it, but it seems it doesn't work properly, it ends up in an endless loop most of the times. This is my code:

int main(){
    double x;
    double sinx;
    int n=1;
    int sign=-1;
    cin>>x;
    sinx=0;
    for(;;) {
        int fact=1;
        for(int i=1;i<=2*n+1;i++){
            fact*=i;
        }
        double term=pow(x,2*n+1)/fact;
        if(term==0){
            break;
        }
        sinx += term * sign;
        sign *= -1;
        n++;

    }
    cout<<sinx;
}

I really tried everything.


Solution

  • EDIT:

    The bug is in integer overflow of fact. There should be a check that integer overflow hasn't happened.

    #include<cassert>
    #include<iostream>
    #include<cmath>
    
    int main(){
        double x;
        double sinx;
        int n=1;
        int sign=-1;
        std::cin>>x;
        sinx=0;
        bool overflow = false;
    
        for(;;) {
            int64_t fact=1;
            for(int i=1;i<=2*n+1;i++){
                old_fact = fact;
                fact = fact * i;
                // check for overflow
                if (fact / i != old_fact) {
                   overflow = true;
                   break;
                }
            }
            if (overflow)
               break;
    
    
            double term=std::pow(x,2*n+1)/fact;
            if(term==0){
                break;
            }
            std::cout<<"n=" << n << ", fact = " << fact << ", term: " << term <<"\n";
            sinx += term * sign;
            sign *= -1;
            n++;
            std::cout<<"sinx=" << sinx<<"\n\n";
        }
        std::cout<<sinx;
    }
    

    godblot link: https://godbolt.org/z/zP8sT6ovq

    Old answer:

    The problem is with checking if a floating point number is exactly equal to zero.

            if(term==0){
    

    This may not ever evaluate to true. It may keep oscillating around a value close to zero. What you could do is to compare if term is arbitrarily close to zero. You can hard code a value like 0.000001 (which I recommend for a class project) or you can use epsilon if you want to get more technical.

    So the code will be like:

    if (std::abs(term) < 0.000001) {
      break;