We already know the problem:
int sum = 0;
for(int i = 1;i<=n;i++){
if (i%2 != 0){
i = -i; // <-- Bad Idea.
// Can you imagine what the sequence of 'i' looks like?
// It just keeps alternating between 1, -1 and 0.
}
sum += i;
}
There's a possible approach that's only variable away from this snippet. I'll wrap it into a function, so that it can be more easily tested.
#include <iostream>
namespace b {
constexpr int alternating_sum(int n)
{
int sum{};
for(int i = 1; i <= n; i++)
{
int value = i; // <-- Let's use this, instead of messing with i.
if ( i % 2 != 0)
{
value = -value;
}
sum += value;
}
return sum;
}
}
int main()
{
// Let's test it:
using namespace b;
static_assert(alternating_sum(1) == -1);
static_assert(alternating_sum(2) == -1 + 2);
static_assert(alternating_sum(3) == -1 + 2 - 3);
static_assert(alternating_sum(4) == -1 + 2 - 3 + 4);
std::cout << "So far, so good...\n";
return 0;
}
I also wrapped it into a namespace
, while avoiding using namespace std
1, because I'd like to play a little more.
Maybe it helps to see how the sequence "grows", so we can add this snippet to the main
function:
for (int i = 1; i <= 10; ++i)
{
std::cout << alternating_sum(i) << '\n';
}
It outputs the following
-1
1
-2
2
-3
3
-4
4
-5
5
That seems like a pattern. One we can reproduce without a loop, with just a little math:
namespace c
{
constexpr int alternating_sum(int n)
{
if ( n % 2 != 0 )
{
return -(n + 1) / 2;
}
else
{
return n / 2;
}
}
}
To test it, we just have to change using namespace b;
into using namespace c;
in main
.
1) Why is "using namespace std;" considered bad practice?