The Python math Module: Everything You Need to Know

The Python math Module: Everything You Need to Know

by Lahiru Liyanapathirana Updated Reading time estimate 40m intermediate python stdlib

In this article, you’ll learn all about Python’s math module. Mathematical calculations are an essential part of most Python development. Whether you’re working on a scientific project, a financial application, or any other type of programming endeavor, you just can’t escape the need for math.

For straightforward mathematical calculations in Python, you can use the built-in mathematical operators, such as addition (+), subtraction (-), division (/), and multiplication (*). But more advanced operations, such as exponential, logarithmic, trigonometric, or power functions, are not built in. Does that mean you need to implement all of these functions from scratch?

Fortunately, no. Python provides a module specifically designed for higher-level mathematical operations: the math module.

By the end of this article, you’ll learn:

  • What the Python math module is
  • How to use math module functions to solve real-life problems
  • What the constants of the math module are, including pi, tau, and Euler’s number
  • What the differences between built-in functions and math functions are
  • What the differences between math, cmath, and NumPy are

A background in mathematics will be helpful here, but don’t worry if math isn’t your strong suit. This article will explain the basics of everything you need to know.

So let’s get started!

Getting to Know the Python math Module

The Python math module is an important feature designed to deal with mathematical operations. It comes packaged with the standard Python release and has been there from the beginning. Most of the math module’s functions are thin wrappers around the C platform’s mathematical functions. Since its underlying functions are written in CPython, the math module is efficient and conforms to the C standard.

The Python math module offers you the ability to perform common and useful mathematical calculations within your application. Here are a few practical uses for the math module:

  • Calculating combinations and permutations using factorials
  • Calculating the height of a pole using trigonometric functions
  • Calculating radioactive decay using the exponential function
  • Calculating the curve of a suspension bridge using hyperbolic functions
  • Solving quadratic equations
  • Simulating periodic functions, such as sound and light waves, using trigonometric functions

Since the math module comes packaged with the Python release, you don’t have to install it separately. Using it is just a matter of importing the module:

Language: Python
>>> import math

You can import the Python math module using the above command. After importing, you can use it straightaway.

Constants of the math Module

The Python math module offers a variety of predefined constants. Having access to these constants provides several advantages. For one, you don’t have to manually hardcode them into your application, which saves you a lot of time. Plus, they provide consistency throughout your code. The module includes several famous mathematical constants and important values:

  • Pi
  • Tau
  • Euler’s number
  • Infinity
  • Not a number (NaN)

In this section, you’ll learn about the constants and how to use them in your Python code.

Pi

Pi (π) is the ratio of a circle’s circumference (c) to its diameter (d):

π = c/d

This ratio is always the same for any circle.

Pi is an irrational number, which means it can’t be expressed as a simple fraction. Therefore, pi has an infinite number of decimal places, but it can be approximated as 22/7, or 3.141.

You can access pi as follows:

Language: Python
>>> math.pi
3.141592653589793

As you can see, the pi value is given to fifteen decimal places in Python. The number of digits provided depends on the underlying C compiler. Python prints the first fifteen digits by default, and math.pi always returns a float value.

So what are some of the ways that pi can be useful to you? You can calculate the circumference of a circle using 2πr, where r is the radius of the circle:

Language: Python
>>> r = 3
>>> circumference = 2 * math.pi * r
>>> f"Circumference of a Circle = 2 * {math.pi:.4} * {r} = {circumference:.4}"
'Circumference of a Circle = 2 * 3.142 * 3 = 18.85'

You can use math.pi to calculate the circumference of a circle. You can also calculate the area of a circle using the formula πr² as follows:

Language: Python
>>> r = 5
>>> area = math.pi * r * r
>>> f"Area of a Circle = {math.pi:.4} * {r} * {r} = {area:.4}"
'Area of a Circle = 3.142 * 5 * 5 = 78.54'

You can use math.pi to calculate the area and the circumference of a circle. When you are doing mathematical calculations with Python and you come across a formula that uses π, it’s a best practice to use the pi value given by the math module instead of hardcoding the value.

Tau

Tau (τ) is the ratio of a circle’s circumference to its radius. This constant is equal to 2π, or roughly 6.28. Like pi, tau is an irrational number because it’s just pi times two.

Many mathematical expressions use 2π, and using tau instead can help simplify your equations. For example, instead of calculating the circumference of a circle with 2πr, we can substitute tau and use the simpler equation τr.

The use of tau as the circle constant, however, is still under debate. You have the freedom to use either 2π or τ as necessary.

You can use tau as below:

Language: Python
>>> math.tau
6.283185307179586

Like math.pi, math.tau returns fifteen digits and is a float value. You can use tau to calculate the circumference of a circle with τr, where r is the radius, as follows:

Language: Python
>>> r = 3
>>> circumference = math.tau * r
>>> f"Circumference of a Circle = {math.tau:.4} * {r} = {circumference:.4}"
'Circumference of a Circle = 6.283 * 3 = 18.85'

You can use math.tau in place of 2 * math.pi to tidy up equations that include the expression 2π.

Euler’s Number

Euler’s number (e) is a constant that is the base of the natural logarithm, a mathematical function that is commonly used to calculate rates of growth or decay. As with pi and tau, Euler’s number is an irrational number with infinite decimal places. The value of e is often approximated as 2.718.

Euler’s number is an important constant because it has many practical uses, such as calculating population growth over time or determining rates of radioactive decay. You can access Euler’s number from the math module as follows:

Language: Python
>>> math.e
2.718281828459045

As with math.pi and math.tau, the value of math.e is given to fifteen decimal places and is returned as a float value.

Infinity

Infinity can’t be defined by a number. Rather, it’s a mathematical concept representing something that is never-ending or boundless. Infinity can go in either direction, positive or negative.

You can use infinity in algorithms when you want to compare a given value to an absolute maximum or minimum value. The values of positive and negative infinity in Python are as follows:

Language: Python
>>> f"Positive Infinity = {math.inf}"
'Positive Infinity = inf'
>>> f"Negative Infinity = {-math.inf}"
'Negative Infinity = -inf'

Infinity is not a numerical value. Instead, it’s defined as math.inf. Python introduced this constant in version 3.5 as an equivalent to float("inf"):

Language: Python
>>> float("inf") == math.inf
True

Both float("inf") and math.inf represent the concept of infinity, making math.inf greater than any numerical value:

Language: Python
>>> x = 1e308
>>> math.inf > x
True

In the above code, math.inf is greater than the value of x, 10308 (the maximum size of a floating-point number), which is a double precision number.

Similarly, -math.inf is smaller than any value:

Language: Python
>>> y = -1e308
>>> y > -math.inf
True

Negative infinity is smaller than the value of y, which is -10308. No number can be greater than infinity or smaller than negative infinity. That’s why mathematical operations with math.inf don’t change the value of infinity:

Language: Python
>>> math.inf + 1e308
inf
>>> math.inf / 1e308
inf

As you can see, neither addition nor division changes the value of math.inf.

Not a Number (NaN)

Not a number, or NaN, isn’t really a mathematical concept. It originated in the computer science field as a reference to values that are not numeric. A NaN value can be due to invalid inputs, or it can indicate that a variable that should be numerical has been corrupted by text characters or symbols.

It’s always a best practice to check if a value is NaN. If it is, then it could lead to invalid values in your program. Python introduced the NaN constant in version 3.5.

You can observe the value of math.nan below:

Language: Python
>>> math.nan
nan

NaN is not a numerical value. You can see that the value of math.nan is nan, the same value as float("nan").

Arithmetic Functions

Number theory is a branch of pure mathematics, which is the study of natural numbers. Number theory usually deals with positive whole numbers or integers.

The Python math module provides functions that are useful in number theory as well as in representation theory, a related field. These functions allow you to calculate a range of important values, including the following:

  • The factorials of a number
  • The greatest common divisor of two numbers
  • The sum of iterables

Find Factorials With Python factorial()

You may have seen mathematical expressions like 7! or 4! before. The exclamation marks don’t mean that the numbers are excited. Rather, “!” is the factorial symbol. Factorials are used in finding permutations or combinations. You can determine the factorial of a number by multiplying all whole numbers from the chosen number down to 1.

The following table shows the factorial values for 4, 6, and 7:

Symbol In Words Expression Result
4! Four factorial 4 x 3 x 2 x 1 24
6! Six factorial 6 x 5 x 4 x 3 x 2 x 1 720
7! Seven factorial 7 x 6 x 5 x 4 x 3 x 2 x 1 5040

You can see from the table that 4!, or four factorial, gives the value 24 by multiplying the range of whole numbers from 4 to 1. Similarly, 6! and 7! give the values 720 and 5040, respectively.

You can implement a factorial function in Python using one of several tools:

  1. for loops
  2. Recursive functions
  3. math.factorial()

First you are going to look at a factorial implementation using a for loop. This is a relatively straightforward approach:

Language: Python
def fact_loop(num):
    if num < 0:
        return 0
    if num == 0:
        return 1

    factorial = 1
    for i in range(1, num + 1):
        factorial = factorial * i
    return factorial

You can also use a recursive function to find the factorial. This is more complicated but also more elegant than using a for loop. You can implement the recursive function as follows:

Language: Python
def fact_recursion(num):
    if num < 0:
        return 0
    if num == 0:
        return 1

    return num * fact_recursion(num - 1)

The following example illustrates how you can use the for loop and recursive functions:

Language: Python
>>> fact_loop(7)
5040

>>> fact_recursion(7)
5040

Even though their implementations are different, their return values are the same.

However, implementing functions of your own just to get the factorial of a number is time consuming and inefficient. A better method is to use math.factorial(). Here’s how you can find the factorial of a number using math.factorial():

Language: Python
>>> math.factorial(7)
5040

This approach returns the desired output with a minimal amount of code.

factorial() accepts only positive integer values. If you try to input a negative value, then you will get a ValueError:

Language: Python
>>> math.factorial(-5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: factorial() not defined for negative values

Inputting a negative value will result in a ValueError reading factorial() not defined for negative values.

factorial() doesn’t accept decimal numbers, either. It will give you a ValueError:

Language: Python
>>> math.factorial(4.3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: factorial() only accepts integral values

Inputting a decimal value results in a ValueError reading factorial() only accepts integral values.

You can compare the execution times for each of the factorial methods using timeit():

Language: Python
>>> import timeit
>>> timeit.timeit("fact_loop(10)", globals=globals())
1.063997201999996

>>> timeit.timeit("fact_recursion(10)", globals=globals())
1.815312818999928

>>> timeit.timeit("math.factorial(10)", setup="import math")
0.10671788000001925

The sample above illustrates the results of timeit() for each of the three factorial methods.

timeit() executes one million loops each time it is run. The following table compares the execution times of the three factorial methods:

Type Execution Time
With loops 1.0640 s
With recursion 1.8153 s
With factorial() 0.1067 s

As you can see from the execution times, factorial() is faster than the other methods. That’s because of its underlying C implementation. The recursion-based method is the slowest out of the three. Although you might get different timings depending on your CPU, the order of the functions should be the same.

Not only is factorial() faster than the other methods, but it’s also more stable. When you implement your own function, you have to explicitly code for disaster cases such as handling negative or decimal numbers. One mistake in the implementation could lead to bugs. But when using factorial(), you don’t have to worry about disaster cases because the function handles them all. Therefore, it’s a best practice to use factorial() whenever possible.

Find the Ceiling Value With ceil()

math.ceil() will return the smallest integer value that is greater than or equal to the given number. If the number is a positive or negative decimal, then the function will return the next integer value greater than the given value.

For example, an input of 5.43 will return the value 6, and an input of -12.43 will return the value -12. math.ceil() can take positive or negative real numbers as input values and will always return an integer value.

When you input an integer value to ceil(), it will return the same number:

Language: Python
>>> math.ceil(6)
6
>>> math.ceil(-11)
-11

math.ceil() always returns the same value when an integer is given as input. To see the true nature of ceil(), you have to input decimal values:

Language: Python
>>> math.ceil(4.23)
5
>>> math.ceil(-11.453)
-11

When the value is positive (4.23), the function returns the next integer greater than the value (5). When the value is negative (-11.453), the function likewise returns the next integer greater than the value (-11).

The function will return a TypeError if you input a value that is not a number:

Language: Python
>>> math.ceil("x")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be real number, not str

You must input a number to the function. If you try to input any other value, then you will get a TypeError.

Find the Floor Value With floor()

floor() will return the closest integer value that is less than or equal to the given number. This function behaves opposite to ceil(). For example, an input of 8.72 will return 8, and an input of -12.34 will return -13. floor() can take either positive or negative numbers as input and will return an integer value.

If you input an integer value, then the function will return the same value:

Language: Python
>>> math.floor(4)
4
>>> math.floor(-17)
-17

As with ceil(), when the input for floor() is an integer, the result will be the same as the input number. The output only differs from the input when you input decimal values:

Language: Python
>>> math.floor(5.532)
5
>>> math.floor(-6.432)
-7

When you input a positive decimal value (5.532), it will return the closest integer that is less than the input number (5). If you input a negative number (-6.432), then it will return the next lowest integer value (-7).

If you try to input a value that is not a number, then the function will return a TypeError:

Language: Python
>>> math.floor("x")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be real number, not str

You can’t give non-number values as input to ceil(). Doing so will result in a TypeError.

Truncate Numbers With trunc()

When you get a number with a decimal point, you might want to keep only the integer part and eliminate the decimal part. The math module has a function called trunc() which lets you do just that.

Dropping the decimal value is a type of rounding. With trunc(), negative numbers are always rounded upward toward zero and positive numbers are always rounded downward toward zero.

Here is how the trunc() function rounds off positive or negative numbers:

Language: Python
>>> math.trunc(12.32)
12
>>> math.trunc(-43.24)
-43

As you can see, 12.32 is rounded downwards towards 0, which gives the result 12. In the same way, -43.24 is rounded upwards towards 0, which gives the value -43. trunc() always rounds towards zero regardless of whether the number is positive or negative.

When dealing with positive numbers, trunc() behaves the same as floor():

Language: Python
>>> math.trunc(12.32) == math.floor(12.32)
True

trunc() behaves the same as floor() for positive numbers. As you can see, the return value of both functions is the same.

When dealing with negative numbers, trunc() behaves the same as ceil():

Language: Python
>>> math.trunc(-43.24) == math.ceil(-43.24)
True

When the number is negative, floor() behaves the same as ceil(). The return values of both functions are the same.

Find the Closeness of Numbers With Python isclose()

In certain situations—particularly in the data science field—you may need to determine whether two numbers are close to each other. But to do so, you first need to answer an important question: How close is close? In other words, what is the definition of close?

Well, Merriam-Webster will tell you that close means “near in time, space, effect, or degree.” Not very helpful, is it?

For example, take the following set of numbers: 2.32, 2.33, and 2.331. When you measure closeness by two decimal points, 2.32 and 2.33 are close. But in reality, 2.33 and 2.331 are closer. Closeness, therefore, is a relative concept. You can’t determine closeness without some kind of threshold.

Fortunately, the math module provides a function called isclose() that lets you set your own threshold, or tolerance, for closeness. It returns True if two numbers are within your established tolerance for closeness and otherwise returns False.

Let’s check out how to compare two numbers using the default tolerances:

  • Relative tolerance, or rel_tol, is the maximum difference for being considered “close” relative to the magnitude of the input values. This is the percentage of tolerance. The default value is 1e-09 or 0.000000001.
  • Absolute tolerance, or abs_tol, is the maximum difference for being considered “close” regardless of the magnitude of the input values. The default value is 0.0.

isclose() will return True when the following condition is satisfied:

abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol).

isclose uses the above expression to determine the closeness of two numbers. You can substitute your own values and observe whether any two numbers are close.

In the following case, 6 and 7 aren’t close:

Language: Python
>>> math.isclose(6, 7)
False

The numbers 6 and 7 aren’t considered close because the relative tolerance is set for nine decimal places. But if you input 6.999999999 and 7 under the same tolerance, then they are considered close:

Language: Python
>>> math.isclose(6.999999999, 7)
True

You can see that the value 6.999999999 is within nine decimal places of 7. Therefore, based on the default relative tolerance, 6.999999999 and 7 are considered close.

You can adjust the relative tolerance however you want depending on your need. If you set rel_tol to 0.2, then 6 and 7 are considered close:

Language: Python
>>> math.isclose(6, 7, rel_tol=0.2)
True

You can observe that 6 and 7 are close now. This is because they are within 20% of each other.

As with rel_tol, you can adjust the abs_tol value according to your needs. To be considered close, the difference between the input values must be less than or equal to the absolute tolerance value. You can set the abs_tol as follows:

Language: Python
>>> math.isclose(6, 7, abs_tol=1.0)
True
>>> math.isclose(6, 7, abs_tol=0.2)
False

When you set the absolute tolerance to 1, the numbers 6 and 7 are close because the difference between them is equal to the absolute tolerance. However, in the second case, the difference between 6 and 7 is not less than or equal to the established absolute tolerance of 0.2.

You can use the abs_tol for very small values:

Language: Python
>>> math.isclose(1, 1.0000001, abs_tol=1e-08)
False
>>> math.isclose(1, 1.00000001, abs_tol=1e-08)
True

As you can see, you can determine the closeness of very small numbers with isclose. A few special cases regarding closeness can be illustrated using nan and inf values:

Language: Python
>>> math.isclose(math.nan, 1e308)
False
>>> math.isclose(math.nan, math.nan)
False

>>> math.isclose(math.inf, 1e308)
False
>>> math.isclose(math.inf, math.inf)
True

You can see from the above examples that nan is not close to any value, not even to itself. On the other hand, inf is not close to any numerical values, not even to very large ones, but it is close to itself.

Power Functions

The power function takes any number x as input, raises x to some power n, and returns xn as output. Python’s math module provides several power-related functions. In this section, you’ll learn about power functions, exponential functions, and square root functions.

Calculate the Power of a Number With pow()

Power functions have the following formula where the variable x is the base, the variable n is the power, and a can be any constant: