二分法。优化 C 代码中的函数

Bisection method. Optimise function in C code

我的老师对我的二分法代码有评论。他说“函数的计算次数没有优化。实际上,在每次迭代中,函数都计算了三次,虽然一次就足够了。”

你能帮我优化一下计算吗?我什至没有看到函数在哪一点计算了 3 次。

#include<stdio.h>
#include<math.h>
#include<time.h>

double f(double x); //Function
int res(int i, double a, double b, double ξ, double ε1, double ε2); //Print result
double Bisection(double a, double b, double ε1, double ε2); //Bisection method

int main()
{
    double a=-10, b=0, ξ, h=0.5, α, x1, x2, ε1, ε2;
    int i=0;

    printf("\nf(x) = 2^x - 2 * cos(x)");
    printf("\nStart of the interval a = %.0lf", a);
    printf("\nEnd of the interval b = %.0lf", b);
    printf("\nEnter error ε1 for function = ");
    scanf("%lf", &ε1);
    printf("Enter error ε2 for argument = ");
    scanf("%lf", &ε2);
    printf("\n\nSOLUTION:");

    //selection of roots
    x1=a;
    x2=x1+h;
    while (x2<=b)
    {
        if ((f(x1)*f(x2))<0) 
        {
            i++;
            printf("\n\n%d) %d root of the function is in the interval [%.1f, %.1f]\n",i, i, x1, x2);
            printf("\nn\t     a\t\t   b\t\t ξ\t     f(ξ)\t     ε1\t\t    ε2\n");
            Bisection(x1,x2,ε1,ε2); //Bisection method
        }
        x1=x2;
        x2=x1+h;
    }
    return 0;
}

//Function
double f(double x) 
{
   double y;
   y=pow(2,x)-2*cos(x);
   return y;
}

//Print result
int res(int i, double a, double b, double ξ, double ε1, double ε2) 
{
   printf("%d\t%10.7f    %10.7f    %10.7f    %10.7f    %e    %e\n", i, a, b, ξ, f(ξ), ε1, ε2);
   return 0;
}

//Bisection method
double Bisection(double a, double b, double ε1, double ε2)
{
    double ξ=(a+b)/2; //Middle of the interval
    double α;
    int i=0;
    if (f(ξ)==0) 
    {
        printf("Root: %f \n\n", ξ);
    }
    else 
    {
        while ((fabs(f(ξ))>ε1) && ((fabs(b-a)/2)>ε2)) //The accuracy of the definition of the root
        {
            if ((f(a)*f(ξ))<0) 
            {
                b=ξ;
            }
            else 
            {
                a=ξ;
            }
            ξ=(a+b)/2;
            res(i+1, a, b, ξ, ε1, ε2); //Print results
            i++;
        }
        printf("Root ξ=%.7f found after %d iterations\n", ξ, i);
        printf("Function f(ξ)=%.10f found after %d iterations\n", f(ξ), i);
    }
    return 0;
}

Results

只包括相关行

替换:

double Bisection(double a, double b, double ε1, double ε2)
{
    double ξ=(a+b)/2;

    if (f(ξ)==0) 

    else 
    {
        while ((fabs(f(ξ))>ε1) && ((fabs(b-a)/2)>ε2))
        {
            if ((f(a)*f(ξ))<0) 

            ξ=(a+b)/2;
        }
   }

double Bisection(double a, double b, double ε1, double ε2)
{
    double ξ=(a+b)/2; 

    double val = f(ξ); // Here is the magic

    if (val==0) 

    else 
    {
        while ((fabs(val)>ε1) && ((fabs(b-a)/2)>ε2))
        {
            if ((f(a) * val )<0) 

            ξ=(a+b)/2;
            val = f(ξ); // And here
       }
   }

我们所说的并不是真正的秘密技巧。它只是将 return 值保存在一个变量中,并尽可能使用该变量而不是函数调用。如果函数的参数发生变化,则需要再次执行该函数。这是一个使字符串大写的简单示例。

void uppercase(char *str) {
    // Bad, because it's not necessary to calculate the string
    // length every iteration.
    for(size_t i=0; i<strlen(str); i++)     
        str[i] = toupper(str[i]);
}

// Instead, do this

void uppercase(char *str) {
    size_t len = strlen(str);    // Precalculate and reuse in loop
    for(size_t i=0; i<len; i++)            
        str[i] = toupper(str[i]);
}