Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Newton's method program (in C) loop running infinitely

This code(attached with the post) in C uses Newton - Raphson method to find roots of a polynomial in a particular interval.

This code works perfectly fine for some polynomials like x^3 + x^2 + x + 1 but runtime gets infinite for some polynomials like x^3 - 6*x^2 + 11*x - 6 . That is this code works fine for polynomials having one or zero root in the entered interval but if more than one roots are present then it runs indefinitely.

Please let me know if someone finds a solution for this. I have written comments in the code to guide the reader but still if anyone finds it difficult to understand, can ask in the comments, I'll explain it.

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<ctype.h>

int check(float num)                          //just a function to check for  the correct input
{
    char c;
    scanf("%c",&c);

    if(isalpha((int)c))
        printf("you entered an alphabet\n");

    else
        printf("you entered a character, please retry\n");

    return 0;
}

float func(float *p,int order,double x)                     //calculates the value of the function required in the formmula in main
{
    double fc=0.0;
    int i;

    for(i=0;i<=order;i++)
    {
        fc=fc+(double)(*p)*pow(x,(double)i);
        p++;
    }

    return fc;
}

float derv(float *q,int order,double x)               //calculates the derivative of the function required in the formmula in main
{     
    double dv=0.0,i;

    for(i=1;i<=order;i++)
    {
        dv=dv+(double)(*q)*(pow(x,(double)(i-1)))*(double)i;
        q++;
    }

    return dv;
}


int main()
{
    float coeff[1000];
    int order,count=0,i,j=0;
    char ch;
    float a,b;
    double val[5];

    printf("roots of polynomial using newton and bisection method\n");
    printf("enter the order of the equation\n");

    while(scanf("%d",&order)!=1)
    {
        printf("invalid input.please retry\n");
        while(getchar()!='\n'){}          
    }     

    printf("enter the cofficients\n");

    for(i=0;i<=order;i++)
    {
        printf("for x^%d  :",order-i);
        printf("\n");

        while(scanf("%f",&coeff[i])!=1)
        {
            check(coeff[i]);
        }   
    }

    while(getchar()!='\n'){}                                 //this clears the buffer accumulated upto pressing enter

    printf("the polynomial you entered is :\n");

    for(i=0;i<=order;i++)
    {
        printf(" %fx^%d ",coeff[i],order-i);
    }

    printf("\n");

    //while(getchar()!='\n'){};

    /* fflush(stdout);
    fflush(stdin);*/

    printf("plese enter the interval domain [a,b]\n");
    printf("enter a and b:\n");
    scanf("%f %f",&a,&b);

    while(getchar()!='\n'){}

    printf("the entered interval is [%f,%f]",a,b);

    fflush(stdout);
    fflush(stdin);

    //this array is used to choose a different value of x to apply newton's formula recurcively in an interval to scan it roperly for 3 roots

    val[0]=(double)b;       
    val[1]=(double)a;
    val[2]=(double)((a+b)/2);

    double t,x=val[0],x1=0.0,roots[10];

    while(1)
    {

        t=x1;
        x1=(x-(func(&coeff[0],order,x)/derv(&coeff[0],order,x)));           //this is the newton's formula

        x=x1;

        if((fabs(t - x1))<=0.0001 && count!=0)
        {
            roots[j]=x;
            j++;
            x=val[j];   // every time a root is encountered this stores the root in roots array and runs the loop again with different value of x to find other roots
            t=0.0;
            x1=0.0;
            count=(-1);

            if(j==3)
                break;
        }

        count++;
    }

    printf("the roots are = \n");

    int p=0;

    for(j=0;j<3;j++)
    {
        if(j==0 && roots[j]>=a && roots[j]<=b)
        {
            printf("  %f  ",roots[j]);
            p++;
        }

        if(fabs(roots[j]-roots[j-1])>0.5 && j!=0 && roots[j]>=a && roots[j]<=b)
        {
            printf(" %f  ",roots[j]);
            p++;
        }
    }

    if(p==0)
        printf("Sorry,no roots are there in this interval \n");

    return 0;
}
like image 522
Masquerade Avatar asked Nov 26 '16 21:11

Masquerade


People also ask

How to create an infinite loop in C?

Next we write the c code to create the infinite loop by using do-while loop with the following example. 4. Goto Statement Next we write the c code to create the infinite loop by using goto statement with the following example. As in the above code the goto statement becomes the infinite loop.

How many times can a for loop run in C?

So the loop run for infinite times. Next, we write the c code to understand the infinite for loop working more clearly with the following example. As in the above code the for loop is running for infinite times and printing the i value that is 10 infinitely.

What are the situations in which infinite loop is used?

In the following situations, this type of loop can be used: All the operating systems run in an infinite loop as it does not exist after performing some task. It comes out of an infinite loop only when the user manually shuts down the system. All the servers run in an infinite loop as the server responds to all the client requests.

Can a macro have an infinite loop?

Later in a main function macro is used by its name, whenever the name of macro comes it gets replaced by its value. An infinite loop is a loop that repeats indefinitely and does not terminate. A program can have infinite loop by intentionally or unintentionally as we have seen above.


1 Answers

You're not calculating the function or the derivative correctly, because you store the coefficients in reverse order but you aren't accounting for that.

When you print out the equation, you do account for it, by printing order-i:

printf(" %fx^%d ",coeff[i],order-i);

So you need to do the same thing in func:

fc=fc+(double)(*p)*pow(x,(double)(order-i));

and derv:

dv=dv+(double)(*q)*(pow(x,(double)((order-i)-1)))*(double)(order-i);

The reason it's working for polynomials like x^3 + x^2 + x + 1 is because in that example all the coefficients are the same so it won't make a difference if you read the array forwards or backwards.

In addition, you may need to account for other reasons the method can fail to converge, as mentioned by Johnathon Leffler in a comment. You can set a maximum number of iterations for your loop and just break out if it exceeds the maximum.

A good way to debug something like this (besides using a debugger of course) is to add a few extra printf statements to show the values that are being calculated. You can sanity check the output by entering the equation into a Google search, it will give an interactive graph of the function.

like image 75
samgak Avatar answered Sep 23 '22 06:09

samgak