The previous article illustrated a very simple example. It was enough to cover the absolute basics, but now let's try something a bit more complex. Unfortunately, this means we're going to have a bit longer of an article. Take a deep breath and get ready to dive in.
Following in line with some math-oriented functions, let's build a function that calculates a number to a specified power.
Just to re-iterate:
53 = 5 x 5 x 5
How can we generalize that? Using loops!
A while loop can execute a bit of code over and over again until a certain condition is met. Here's a bit of an example:
int i = 0;
int max = 7;
while (i < max)
{
// do something
i = i + 2;
}Breaking down the while statement, we see that it only has a conditional bit; we loop while the variable i is less than max. Inside the body of the while loop, we do something, and then modify the value of i.
Note that we don't just have to modify the left hand side of the equation. We could just have easily modified the right hand side. However, common convention is that we usually don't.
Wait ... what's this about conditionals? What's happening there with that i < max bit of code in the while line?
Conditionals are essentially tests. Does something evaluate to 'true' or 'false'?
Computers tend to represent 'true' and 'false' as a bit - a 1 or a 0, an on or off. So what the conditional here is testing is: is the current value of i less than (the < operator) the current value of max. While that conditional is true, we continue to loop. Once that conditional evaluates to false, we stop looping an proceed to the code after the body of the loop (the next line after the loops }).
Also, a 'true' or a 'false' is also represented as a data type called a boolean (bool keyword in C/C++).
Get used to writing conditional statements. Programming is all about writing conditional statements. This will become evident shortly.
There's also a variation on a while loop, called a do-while. It looks like this:
int i = 0;
int max = 7;
do
{
// do something
i = i + 2;
} while (i < max);There is really only one difference between a while and do-while loop: a do-while loop is guaranteed to execute the body of the loop once. You aren't guaranteed that with a regular while loop.
Consider the following:
int i = 10;
int max = 7;
do
{
printf("I'm in the do-while loop\n");
i = i + 2;
} while (i < max);
while (i < max)
{
printf("I'm in the while loop\n");
i = i + 2;
}This generates the following result:
I'm in the do-while loopAnother type of loop is called a for loop, defined in C/C++ like this:
for (int i = 0; i < 5; i++)
{
// do stuff
}for is another C/C++ keyword that indicates that we are going to loop over a block of code (what's contained in the curly braces { }) until a certain condition is met.
The formal syntax for a for loop looks like this:
for ( <initialization part>; <conditional part>; <post loop part> )
The initialization part is just exactly that - it allows us to create some temporary variable to use as a counter. In this example, we create an integer variable (int is yet another data type - it holds a whole number) that we initialize with a value of 0.
The conditional part is evaluated at the start and subsequent iteration of the loop. We only iterate through the loop if it evaluates to true. So we only enter the loop while the value of i is less than 5.
The post loop part happens at the end of the loop. In this case, we use the ++ operator to increment the variable i by 1. The ++ operator is built in to C/C++. So is -- which subtracts 1 from a variable.
A for loop can be thought of exactly like a while loop with the following syntax:
<initialization part>
while (<conditional part>)
{
// do stuff
<post loop part>
}We now come to the point where we figure out how to use those loops to generate a 'raise to the power of' function. Remember this?
53 = 5 x 5 x 5
Can you see how we're looping there? Kinda awesome, right? Well, we can code that up fairly easily:
// Calculating an exponent
#include <stdio.h>
float calcPow(float base, float exponent)
{
float result = base;
for (int index = 0; index < (exponent - 1); index++)
{
result *= base;
}
return result;
}
int main()
{
printf("5 to the power of 3 is: %f\n", calcPow(5, 3));
}I think everything there is fairly obvious at this point. Except for that for loop. Take a look:
for (int index = 0; index < (exponent - 1); index++)
Why is our conditional set to index < (exponent -1)?
That has to do with how the body of the loop is set up. Look again:
float result = base;
for (int index = 0; index < (exponent - 1); index++)
{
result *= base;
}We've already set result to base - so we don't have to loop exponent times. However, let's imagine what the program is actually doing. Consider the following table:
| iteration | index value | test | exponent | result value |
|---|---|---|---|---|
| 1 | 0 | 0<3 (True) | 3 | 35.0 |
| 2 | 1 | 1<3 (True) | 3 | 325.0 |
| 3 | 2 | 2<3 (True) | 3 | 3125.0 |
| 4 | 3 | 3<3 (False) | 3 | - |
These kinds of tables can be invaluable when debugging what's going on in a bit of code. We're essentially walking through, step by step, what the code is doing and writing down what we expect to see.
Executing this program results in the following:
5 to the power of 3 is: 125.000000That's great! Done!
Well, not quite. The exponent can be a positive or negative number. Our calcPow function doesn't actually do the right thing:
// Calculating an exponent
#include <stdio.h>
float calcPow(float base, float exponent)
{
float result = base;
for (int index = 0; index < (exponent - 1); index++)
{
result *= base;
}
return result;
}
int main()
{
printf("5 to the power of 3 is: %f\n", calcPow(5, 3));
printf("5 to the power of -3 is: %f\n", calcPow(5, -3));
}5 to the power of 3 is: 125.000000
5 to the power of -3 is: 5.000000Can you see what the problem is? Let's bring up that handy table again:
| iteration | index value | test | exponent | result value |
|---|---|---|---|---|
| 1 | 0 | 0<-3 (False) | -3 | - |
Also, the logic behind calculating a negative exponent is wrong. A negative exponent is calculated like so:
5-3 = 1 / (5 x 5 x 5)
We're almost there. We just need to get our code to do the right thing. We need some way to have our code do one thing if we have a positive exponent, and something else if the exponent is negative.
For that, we need a branching statement. if/else to our rescue!
What an if statment does is perform some calculations 'if' a conditional statement is true. You can also add an else to deal with the false part. Here's what it looks like:
if (<conditional part>)
{
// Do something here
}
else // This is optional!
{
// Do this part if <conditional part> evaluates to false
}Let's put that to use in our power calcuation code
// Calculating an exponent
#include <stdio.h>
float calcPow(float base, float exponent)
{
int iterations = exponent;
if (exponent < 0)
{
iterations *= -1.0f;
}
float result = base;
for (int index = 0; index < (iterations - 1); index++)
{
result *= base;
}
if (exponent < 0)
{
result = 1.0f / result;
}
return result;
}
int main()
{
printf("5 to the power of 3 is: %f\n", calcPow(5, 3));
printf("5 to the power of -3 is: %f\n", calcPow(5, -3));
}
5 to the power of 3 is: 125.000000
5 to the power of -3 is: 0.008000proper negative exponent handling
A bit more to unpack here.
int iterations = exponent; // iterations is a temp variable for how many times we should loop
if (exponent < 0) // if exponent is less than 0
{
iterations *= -1.0f; // we negate it, making it a positive number.
} // This bit stays the same.
float result = base;
for (int index = 0; index < (iterations - 1); index++)
{
result *= base;
} if (exponent < 0) // if the exponent is less than 0
{
result = 1.0f / result; // the actual value is 1 / (5 x 5 x 5)
} // This also stays the same
return result;
}I've purposely left a bug in this bit of code. It's actually a really big bug. I'd like to see if you can find it. In my next article, I'll post the bug and the solution for it.
As well, can you think of any ways to simplify this program? Without using any additional libraries?
Can you also write a version of this program that works with integer numbers?
Now you've actually got some homework! So until next time, play around with the C++ shell, take a look at the Visual Studio solution that exists in this Github repo and experiment!
You can head back to the main article page here and continue on with the next article.
End Of Line.
-Ash
- Technical reference for the language online: C++ Reference
- Interactive C++ shell: C++ shell
- An alternative (code. compile. run. debug): OnlineGDB