牛顿法程序(C 语言)循环无限运行

Posted

技术标签:

【中文标题】牛顿法程序(C 语言)循环无限运行【英文标题】:Newton's method program (in C) loop running infinitely 【发布时间】:2017-04-10 22:24:14 【问题描述】:

C 中的这段代码(附在帖子中)使用Newton - Raphson method 在特定区间内查找多项式的根。

此代码对于像 x^3 + x^2 + x + 1 这样的多项式非常有效,但对于像 x^3 - 6*x^2 + 11*x - 6 这样的一些多项式,运行时会变得无限。也就是说,此代码适用于在输入区间内具有一个或零根的多项式,但如果存在多个根,则它会无限期地运行。

如果有人找到解决方案,请告诉我。我在代码中写了cmets来指导读者,但是如果有人觉得难以理解,可以在cmets中提问,我会解释的。

#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;

【问题讨论】:

Newton's Method 上的***文章概述了它无法收敛的原因。想必您已经遇到过其中的一些原因。 【参考方案1】:

您没有正确计算函数或导数,因为您以相反的顺序存储系数,但您没有考虑到这一点。

当您打印出方程式时,您确实通过打印order-i

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

所以你需要在func做同样的事情:

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

derv:

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

它适用于像 x^3 + x^2 + x + 1 这样的多项式的原因是,在该示例中,所有系数都是相同的,因此如果您向前或向后读取数组,它不会有任何区别。

此外,您可能需要考虑该方法无法收敛的其他原因,正如 Johnathon Leffler 在评论中提到的那样。您可以为循环设置最大迭代次数,如果超过最大值就退出。

调试这样的东西的好方法(当然除了使用调试器)是添加一些额外的 printf 语句来显示正在计算的值。您可以通过在 Google 搜索中输入方程来检查输出,它会给出函数的交互式图表。

【讨论】:

以上是关于牛顿法程序(C 语言)循环无限运行的主要内容,如果未能解决你的问题,请参考以下文章

matlab中牛顿法程序

matlab中牛顿法编程

A-03 牛顿法和拟牛顿法

牛顿法与拟牛顿法的区别与联系

开根号(二分法牛顿法)

第十一章 拟牛顿法