Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++17 if init for the while loop?

Tags:

c++

c++17

c++14

For some home work I'm doing the following:

int main() {

    ofstream file("log.txt");

    file << setw(5)  <<  "i"
         << setw(15) <<  "h"
         << setw(15) <<  "n"
         << setw(15) <<  "sum"
         << setw(15) <<  "diff"
         << endl;

    auto write2file = [&file](int i, double h, double n, double sum, double diff) {
        file << setw(5)  << i
             << setw(15) << h
             << setw(15) << n
             << setw(15) << sum
             << setw(15) << diff
             << endl;
    };

    double a = 0;
    double b = 2;
    int n = 1;
    double h = (b-a)/n;
    double sum = sum_analytic;
    double diff = 1;

    while (diff > pow(10, -4)) {
        h = (b-a)/++n;
        sum = ntgrt(a, b, n, h);
        diff = abs(sum - sum_analytic);

        static int i = 0;
        write2file(++i, h, n, sum, diff);
    }
}

Considering the C++17 if init feature (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html) I'm kind of seing the same pattern here when I declare h, sum and diff outside the while loop but they are used only inside.

Is there a better way to write it, may be taking advantage of C++17 features?

like image 495
KcFnMi Avatar asked May 27 '17 20:05

KcFnMi


Video Answer


2 Answers

Then what you want is a for loop:

for(double diff = 1; diff > pow(10, -4);)
{
    double h = (b-a)/++n;
    double sum = ntgrt(a, b, n, h);
    diff = abs(sum - sum_analytic);
    ....
}

There was no point in adding this capability to while since you can just use for and leave off the increment statement.

like image 155
Nicol Bolas Avatar answered Nov 15 '22 10:11

Nicol Bolas


I'd start with some C++98 features to reduce repetition.

template <class I, class F>
void write2file(std::ostream &os, I i, F h, I n, F sum, F diff) {
    using std::setw;

    os  << setw(5) << i
        << setw(15) << h
        << setw(15) << n
        << setw(15) << sum
        << setw(15) << diff
        << "\n";
}

// ...
write2file(file, "i", "h", "n", "sum", "diff");


// ...
write2file(file, ++i, h, n, sum, diff);

It would appear that when they're used, i and n always have the same value. I'd just use one of the two rather than both.

Your pow(10, -4) would probably be better off as 1e-4.

I think some good use of C++98 can probably clean up the loop as well. I'd move it into a function template, something on this general order:

template <typename F>
void show_convergence(double a, double b, F f, double sum_a, std::ostream &os) {
    double diff = 1.0;

    for (int n=1; diff > 1e-4; n++) {
        double h = (b-a)/n;
        double sum = f(a, b, n, h);
        diff = abs(sum-sum_a);
        write2file(os, n, h, sum, diff);
    }
}

Technically, this wouldn't have to be a template--but it's fairly harmless, and avoids the ugliness of a pointer to a function (which can also lead to a fair degree of inefficiency). Then you'd call this something like this:

show_convergence(0, 2, ntgrt, sum_analytic, file);
like image 28
Jerry Coffin Avatar answered Nov 15 '22 09:11

Jerry Coffin