cmath
Math and programming go hand in hand, especially in game development. We’ll cover the core concepts throughout this chapter, starting from the basics and moving on to concepts that allow us to implement things like virtual cameras and physics systems.
In this first lesson, we're starting with the fundamentals - exponents and square roots. We'll explore how these work in C++, look at different ways to implement them, and start thinking about performance considerations. This sets the stage for the more complex math concepts we'll tackle as we move forward.
Exponentiation is the process of raising a number to the power of another number. We can think of it as multiplying a number by itself, multiple times.
The number we start with is called the base, and the number of times it is multiplied by itself is called the power, or the exponent. For example:
We generally represent this operation with a superscript notation, for example:
The most common form of exponentiation we will see is raising a number to the power of , for example, .
An operation like this, where the exponent is , is commonly called squaring. The result of such an operation is called the square of the base number.
For example, the square of is , because .
In the order of operations, exponentiation happens before multiplication, but after brackets/parentheses. For example:
<cmath>
and std::pow()
To access the standard libraries math utilities, we need to include <cmath>
:
#include <cmath>
cmath
not foundIn some compilers, the <cmath>
header may not be found. It may be necessary to #include <cmath.h>
instead.
After including cmath
or math.h
the pow
function is now available within the std
namespace:
#include <iostream>
#include <cmath>
int main() {
std::cout << "2 to the power of 3 is "
<< std::pow(2, 3);
}
2 to the power of 3 is 8
When we need to raise something to a small power, we don't need a helper function. For example, to raise a
to the power of 2
, it's often preferred to implement that as a * a
rather than std::pow(a, 2)
SDL_pow()
and SDL_powf()
When we’re using SDL, alternative to std::pow()
are available in the form of SDL_pow()
which accepts and returns double
values, and SDL_powf()
which accepts and returns float
values:
#include <iostream>
#include <SDL.h>
int main() {
std::cout << "2 to the power of 3 is "
<< SDL_pow(2, 3);
std::cout << "\n3 to the power of 4 is "
<< SDL_powf(3, 4);
}
2 to the power of 3 is 8
3 to the power of 4 is 81
Finding the square root of a number is, in effect, reversing the process of squaring. For example, the square root of 25 is the number that, if squared, would result in 25.
In other words, the square root of is the value of such that . We saw, from the previous section, that an answer is , because . Therefore, the square root of is
Square roots are often denoted using the radical sign, which looks like this:
Expressions of any length can appear under a radical sign. That expression should be resolved before calculating the square root. For example:
std::sqrt()
To calculate square roots in our programs, the standard library includes std::sqrt()
function within <cmath>
:
#include <cmath>
#include <iostream>
int main() {
std::cout << "The square root of 25 is "
<< std::sqrt(25);
}
The square root of 25 is 5
SDL_sqrt()
and SDL_sqrtf()
Programming a computer to calculate the square root of an input variable is not as easy as it seems. Many different algorithms can be used, each with its advantages and disadvantages. SDL provides optimized implementations that favor speed over maximum precision.
The standard library's std::sqrt()
function has the advantage of being highly accurate but may be slower than approximation methods. This is rarely the trade-off we want when working with graphics, particularly when we may be doing thousands of these calculations per frame.
Typically, we prefer a faster implementation that gets an approximate answer. When we’re using SDL, we can use the SDL_sqrt()
function, which returns and accepts double
values, or SDL_sqrtf()
which returns and accepts float
values:
#include <SDL.h>
#include <iostream>
int main() {
std::cout << "The square root of 25 is "
<< SDL_sqrt(25.0);
std::cout << "\nThe square root of 36 is "
<< SDL_sqrtf(36.0f);
}
The square root of 25 is 5
The square root of 36 is 6
You may have noted that equations like have multiple possible solutions:
This means that both and are solutions (or roots) to the equation . Such solutions are commonly denoted using the symbol. For example, if , then
However, it is commonly the case that we are only looking for the positive root, sometimes also called the principal root. The radical notation, such as , indicates we only want the positive root. As such, the only solution to is .
What if we wanted to get the square root of -25
? There's no real number that can be multiplied by itself to result in -25
, or any other negative number.
Because of this, when we're using square root functions, we typically want to make sure that the thing we're trying to calculate the square root of is positive. If our program ever finds itself needing to get the square root of a negative number, it's likely we made a mistake in our logic somewhere.
This lesson has introduced you to implementing mathematical operations that are fundamental to game development and graphics programming.
We've covered exponentiation and square roots, exploring both the standard library implementations and the optimized SDL versions. Key takeaways:
std::pow()
for calculating powersSDL_pow()
and SDL_powf()
functions offer performance-focused alternatives for graphics codestd::sqrt()
in the standard library and SDL_sqrt()
/SDL_sqrtf()
in SDLx * x
) is often preferredcmath
Understand the math foundations needed for game programming in C++, including power and root functions.
Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games