質問

I'm having issues with my adaptive trapezoidal rule algorithm in C++ -- basically, regardless of the tolerance specified, I get the same exact approximation. The recursion is supposed to stop very early for large tolerances (since abs(coarse-fine) is going to be smaller than 3.0*large tolerance and minLevel of recursion is about 5).

However, what this function does is run the maximum number of times regardless of choice of tolerance. Where did I mess up? EDIT: Perhaps there are issues in my helper functions?

double trap_rule(double a, double b, double (*f)(double),double tolerance, int count)
{
    double coarse = coarse_helper(a,b, f); //getting the coarse and fine approximations from the helper functions
    double fine = fine_helper(a,b,f);

    if ((abs(coarse - fine) <= 3.0*tolerance) && (count >= minLevel))
        //return fine if |c-f| <3*tol, (fine is "good") and if count above
        //required minimum level
    {
        return fine;
    }
    else if (count >= maxLevel)
        //maxLevel is the maximum number of recursion we can go through
    {
        return fine;

    }
    else
    {
        //if none of these conditions are satisfied, split [a,b] into [a,c] and [c,b] performing trap_rule
        //on these intervals -- using recursion to adaptively approach a tolerable |coarse-fine| level
        //here, (a+b)/2 = c
        ++count;
        return  (trap_rule(a, (a+b)/2.0, f, tolerance/2.0, count) + trap_rule((a+b)/2.0, b, f, tolerance/2.0, count));
    }
}


EDIT: Helper and test functions:

//test function
double function_1(double a)
{
    return pow(a,2);
}

//"true" integral for comparison and tolerances




//helper functions

double coarse_helper(double a, double b, double (*f)(double))
{
    return 0.5*(b - a)*(f(a) + f(b)); //by definition of coarse approx
}


double fine_helper(double a, double b, double (*f)(double))
{
    double c = (a+b)/2.0;
    return 0.25*(b - a)*(f(a) + 2*f(c) + f(b)); //by definition of fine approx
}

double helper(double a, double b, double (*f)(double x), double tol)
{
    return trap_rule(a, b, f, tol, 1);
}

And here's what's in main():

std::cout << "First we approximate the integral of f(x) = x^2 on [0,2]" << std::endl;

    std::cout << "Enter a: ";
    std::cin >> a;

    std::cout << "Enter b: ";
    std::cin >> b;

    true_value1 = analytic_first(a,b);

    for (int i = 0; i<=8; i++)
    {
        result1 [i] = helper(a, b, function_1, tolerance[i]);
        error1 [i] = fabs(true_value1 - result1 [i]);
    }

    std::cout << "(Approximate integral of x^2, tolerance, error )" << std::endl;
    for (int i = 0; i<=8; i++)
    {
        std::cout << "(" << result1 [i] << "," << tolerance[i] << "," << error1[i] << ")" << std::endl;
    }
役に立ちましたか?

解決

I find that exactly the opposite of what you suggest is happening --- the algorithm is terminating after only minLevel steps --- and the reason is due to your usage of abs, rather than fabs in the tolerance test. The abs is converting its argument to an int and thus any error less than 1 is getting rounded to zero.

With the abs in place I get this output from a very similar program:

(0.333496,0.001,0.00016276)
(0.333496,0.0001,0.00016276)
(0.333496,1e-05,0.00016276)
(0.333496,1e-06,0.00016276)
(0.333496,1e-07,0.00016276)
(0.333496,1e-08,0.00016276)
(0.333496,1e-09,0.00016276)
(0.333496,1e-10,0.00016276)
(0.333496,1e-11,0.00016276)

Replacing with fabs I get this:

(0.333496,0.001,0.00016276)
(0.333374,0.0001,4.06901e-05)
(0.333336,1e-05,2.54313e-06)
(0.333334,1e-06,6.35783e-07)
(0.333333,1e-07,3.97364e-08)
(0.333333,1e-08,9.93411e-09)
(0.333333,1e-09,6.20882e-10)
(0.333333,1e-10,3.88051e-11)
(0.333333,1e-11,9.7013e-12)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top