Exponents and cmath

Understand the math foundations needed for game programming in C++, including power and root functions.

Ryan McCombe
Updated

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:

  • 22 to the power of 22 is equivalent to 2×22 \times 2, which is equal to 44
  • 22 to the power of 33 is equivalent to 2×2×22 \times 2 \times 2, which is equal to 88
  • 33 to the power of 22 is equivalent to 3×33 \times 3, which is equal to 99

We generally represent this operation with a superscript notation, for example:

  • 22 to the power of 22 is written as 222^2
  • 22 to the power of 33 is written as 232^3
  • 33 to the power of 22 is written as 323^2

The most common form of exponentiation we will see is raising a number to the power of 22, for example, 525^2.

An operation like this, where the exponent is 22, is commonly called squaring. The result of such an operation is called the square of the base number.

For example, the square of 55 is 2525, because 52=255^2 = 25.

Order Of Operations

In the order of operations, exponentiation happens before multiplication, but after brackets/parentheses. For example:

  • 2×22=2×4=82 \times 2^2 = 2 \times 4 = 8
  • (2×2)2=42=16(2 \times 2)^2 = 4^2 = 16

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 2525 is the value of xx such that x2=25x^2 = 25. We saw, from the previous section, that an answer is 55, because 52=255^2 = 25. Therefore, the square root of 2525 is 55

Square roots are often denoted using the radical sign, which looks like this: 25\sqrt{25}

Expressions of any length can appear under a radical sign. That expression should be resolved before calculating the square root. For example: 50+25×2=100=10\sqrt{50 + 25 \times 2} = \sqrt{100} = 10

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 aba^b represents aa raised to the power of bb
  • C++'s standard library provides std::pow() for calculating powers
  • SDL's SDL_pow() and SDL_powf() functions offer performance-focused alternatives for graphics code
  • Square roots are calculated with std::sqrt() in the standard library and SDL_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
Next Lesson
Lesson 97 of 129

Spaces, Vectors and Coordinates

Learn the fundamentals of coordinate systems and vectors to create spatial representations

Have a question about this lesson?
Purchase the course to ask your own questions