2
\$\begingroup\$

I am to compute recurrently (not necessarily recursively) the y, where $$y = {x}^{2n} + {x}^{2(n-1)} + ... + {x}^{4} + {x}^{2} + x$$

Here is what I am doing:

#include <iostream>
using namespace std;

double polynom(unsigned, double);

int main(void)
{
    cout << polynom(2, 3) << endl;
    return 0;
}

double polynom(unsigned n, double x)
{
    double currentAdd(x);
    double res(0);
    while (n)
    {
        res += currentAdd;
        currentAdd *= currentAdd;
        --n;
    }
    return res;
}

Is it possible to do it better?

\$\endgroup\$
  • \$\begingroup\$ What do you mean by "recurrent"? The only association that comes to my mind is recursion. \$\endgroup\$ – Ben Steffan Nov 19 '17 at 17:36
  • 2
    \$\begingroup\$ Also, better in what aspect? Performance? Code clarity? Algorithm? \$\endgroup\$ – Ben Steffan Nov 19 '17 at 17:39
  • 3
    \$\begingroup\$ Are you doing "even powers of x" or "2**n powers of x"? Your loop seems to be computing the latter. (x^4 times x^4 is x^8, not x^6) \$\endgroup\$ – Austin Hastings Nov 19 '17 at 18:20
  • 1
    \$\begingroup\$ Wait, why do you compute x? x is x^1 which is odd? \$\endgroup\$ – Dair Nov 19 '17 at 19:04
  • 2
    \$\begingroup\$ Furthermore: 3 + 3^2 + 3^4 + 3^6 = 822, your program outputs 6654 \$\endgroup\$ – Dair Nov 19 '17 at 19:06
7
\$\begingroup\$

Don't do this:

using namespace std;

See: Why is “using namespace std” considered bad practice?

Its a bad habits you should not get into doing (even for small programs). Bad habits bite you in the butt when you get to larger projects and forget to stop doing them.

Comments

There are a couple of things I would do differently. But I can't say you are doing them wrong.

I prefer not to use unsigned for numeric values.

double polynom(unsigned, double);

There is no way to check that what was passed was not negative. I can easily call this with:

polynom(-1, 2); // Compiler is happy to convert that -1 to a very large 
                // positive number without an y errors. On the reciving
                // side you can not tell if it was an error.

There are very few times when you need the extra bit for larger positive numbers. Any time I have come across this type of case I have just used a larger integer type (not swapped to the unsigned version).

Unsigned values should be reserved for bit masks in user code.

Don't use return in main.

int main(void)
{
    return 0;
}

If you don't put a return at the end of main() then the compiler will automatically plant code to return 0. So it is not technically needed.

Additionally not using the return 0 is a way to indicate that your application can never fail. Note: return 0 indicates a success to the OS and the compiler is planting it by default to indicate successful termination.

So when I see a return 0 at the end of main() I also start to scan the rest of main() to see if there are any other returns (with non zero value) that will indicate the error conditions of the application.

Initialization

This is fine.

    double currentAdd(x);
    double res(0);

But personally I think the = sign provides more context.

    double currentAdd = x;
    double res        = 0;

Prefer for() over while()

This is so 50/50. Its just that for() loops can be slightly more compact.

    while (n)
    {
        --n;
    }
    // over
    for(;n; --n)
    {
    }

Would not worry too much about it though.

\$\endgroup\$
  • 1
    \$\begingroup\$ Hmmm... ;n; Looks kind of funny... But +1 for the unsigined comment I see this happen all the time. (Well alternatively, don't check unsigned stuff). \$\endgroup\$ – Dair Nov 19 '17 at 18:54
  • \$\begingroup\$ What if n is checked for negatives before passing it into the function? In the past, I've used unsigned in places where negative values shouldn't be used anyway. They simply didn't exist in that environment and user input was not taken. If you make a number unsigned, at least it can't accidentally be negative either (in case of overflow, for example). Do I conclude correctly from your post signed integers should be preferred anyway (unless the exception of bit masks mentioned)? \$\endgroup\$ – Mast Nov 19 '17 at 20:08
  • \$\begingroup\$ @Mast. It can't be accidentally negative and you only have positive numbers. Then using signed values does not hurt you (and you can validate the input if things go wrong). BUT using unsigned you can not validate if things happened accidentally (and with c++ auto conversions there are lots of opportunities for accidents). The was a panel talk about this at cppcon because std::size_t is unsigned. The general consensus is that it was a mistake (but its too late now and we are stuck with it). \$\endgroup\$ – Martin York Nov 19 '17 at 21:59
  • \$\begingroup\$ @Mast Personally I would always use signed values for numbers. BUT I don't see it as that incorrect to use unsigned (I just think it is safer to use signed values). \$\endgroup\$ – Martin York Nov 19 '17 at 22:05
  • \$\begingroup\$ You are saying that it is a bad idea to use unsigned since the compiler won`t tell you if you pass a negative number. But will it tell you that if you pass a negative number by using int? \$\endgroup\$ – trafalgarLaww Nov 20 '17 at 10:04

Not the answer you're looking for? Browse other questions tagged or ask your own question.