Exponents and cmath
Understand the math foundations needed for game programming in C++, including power and root functions.
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.
Exponents
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:
- to the power of is equivalent to , which is equal to
- to the power of is equivalent to , which is equal to
- to the power of is equivalent to , which is equal to
We generally represent this operation with a superscript notation, for example:
- to the power of is written as
- to the power of is written as
- to the power of is written as
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 .
Order Of Operations
In the order of operations, exponentiation happens before multiplication, but after brackets/parentheses. For example:
The cmath
Header and std::pow()
To access the standard libraries math utilities, we need to include <cmath>
:
#include <cmath>
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
Using 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
Square Root
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:
Using 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
Using 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
Summary
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:
- Exponentiation involves a base number raised to a power (exponent)
- The notation represents raised to the power of
- C++'s standard library provides
std::pow()
for calculating powers - SDL's
SDL_pow()
andSDL_powf()
functions offer performance-focused alternatives for graphics code - Square roots are calculated with
std::sqrt()
in the standard library andSDL_sqrt()
/SDL_sqrtf()
in SDL - SDL's math functions typically prioritize speed over maximum precision
- For simple operations like squaring, direct multiplication (e.g.,
x * x
) is often preferred - Be cautious with square roots of negative numbers
Spaces, Vectors and Coordinates
Learn the fundamentals of coordinate systems and vectors to create spatial representations