Math Library
While the arithmetic and logic operators represent the basic operations that our [[CPU]] can perform, there are many other common math functions that com in handy. Since they are so common, programming languages usually have a math library that provides these functions. Logarithms, trigonometry and random number generation are just of few of the types of functions typically provided.
Math Constants
Math constants provide commonly used mathematical constanst to the highest precesion available. Some of the more useful math constants are summarized below.
| Constant | Description |
|---|---|
| math.e | Euler's constant [[ℯ]], base of the natural logarithm |
| math.pi | [[π]], Ratio of a circle's circumference to its diameter |
Math Functions
These most useful math functions are summarized below.
| Function | Description |
|---|---|
| abs(x) | [[Absolute value]] of x |
| math.acos(x) | [[Arc cosine]] of x, result is in the range [0,π] [[Radians]] |
| math.asin(x) | [[Arc sine]] of x, result is in the range [-π/2,π/2] [[Radians]] |
| math.atan(x) | [[Arc tangent]] of x, result is in the range [-π/2,π/2] [[Radians]] |
| math.atan2(y,x) | Angle θ from the conversion of [[rectangular coordinates]] (x,y), result is in the range [-π,π] [[Radians]] |
| math.ceil(x) | Smallest integer value greater than or equal to x |
| math.cos(x) | [[Cosine]] of x (in [[Radians]]) |
| math.exp(x) | [[ℯ]] rasied to the power x, i.e. ℯx |
| math.floor(x) | Largest integer less than x |
| math.log(x) | [[Natural logarithm]] of x |
| max(x,y) | Larger of x and y |
| min(x,y) | Smaller of x and y |
| math.pow(x,y) | x raised to the power y, i.e. xy |
| random.random() | [[Pseudorandom]] number on the interval [0,1) |
| round(x) | Nearest integer to x |
| math.sin(x) | [[Sine]] of x (in [[Radians]]) |
| math.sqrt(x) | [[Square root]] of x |
| math.tan(x) | [[Tangent]] of x (in [[Radians]]) |
Be sure to add the following import statements to the top of your program in order to use these math functions and constants.
from Utils import *
import math
import random
The program below illustrates the use of the floating point math functions.
#!/usr/bin/env python3;
###############################################################################
# This program demonstrates the math library.
#
# Copyright © 2016 Richard Lesh. All rights reserved.
###############################################################################
import Utils
import math
import random
# Begin Main
a = math.pi / 6
b = math.pi / 4
c = -a * 2
d = -b * 2
e = math.e
print("pi = {0:f}".format(math.pi))
print("e = {0:f}".format(math.e))
# abs, floor, ceil, round, trunc, min, max
print("abs({0:f}) = {1:f}".format(a, abs(a)))
print("abs({0:f}) = {1:f}".format(c, abs(c)))
print("floor({0:f}) = {1:f}".format(a, math.floor(a)))
print("floor({0:f}) = {1:f}".format(c, math.floor(c)))
print("ceil({0:f}) = {1:f}".format(a, math.ceil(a)))
print("ceil({0:f}) = {1:f}".format(c, math.ceil(c)))
print("round({0:f}) = {1:f}".format(a, round(a)))
print("round({0:f}) = {1:f}".format(c, round(c)))
print("trunc({0:f}) = {1:f}".format(a, math.trunc(a)))
print("trunc({0:f}) = {1:f}".format(c, math.trunc(c)))
print("min({0:f}, {1:f}) = {2:f}".format(a, c, min(a, c)))
print("max({0:f}, {1:f}) = {2:f}".format(a, c, max(a, c)))
# sin, cos, tan, atan, atan2, acos, asin
print("sin({0:f}) = {1:f}".format(a, math.sin(a)))
print("sin({0:f}) = {1:f}".format(b, math.sin(b)))
print("sin({0:f}) = {1:f}".format(c, math.sin(c)))
print("sin({0:f}) = {1:f}".format(d, math.sin(d)))
print("cos({0:f}) = {1:f}".format(a, math.cos(a)))
print("cos({0:f}) = {1:f}".format(b, math.cos(b)))
print("cos({0:f}) = {1:f}".format(c, math.cos(c)))
print("cos({0:f}) = {1:f}".format(d, math.cos(d)))
print("tan({0:f}) = {1:f}".format(a, math.tan(a)))
print("tan({0:f}) = {1:f}".format(b, math.tan(b)))
print("tan({0:f}) = {1:f}".format(c, math.tan(c)))
print("asin({0:f}) = {1:f}".format(math.sin(a), math.asin(math.sin(a))))
print("asin({0:f}) = {1:f}".format(math.sin(b), math.asin(math.sin(b))))
print("asin({0:f}) = {1:f}".format(math.sin(c), math.asin(math.sin(c))))
print("asin({0:f}) = {1:f}".format(math.sin(d), math.asin(math.sin(d))))
print("acos({0:f}) = {1:f}".format(math.cos(a), math.acos(math.cos(a))))
print("acos({0:f}) = {1:f}".format(math.cos(b), math.acos(math.cos(b))))
print("acos({0:f}) = {1:f}".format(math.cos(c), math.acos(math.cos(c))))
print("acos({0:f}) = {1:f}".format(math.cos(d), math.acos(math.cos(d))))
print("atan({0:f}) = {1:f}".format(math.tan(a), math.atan(math.tan(a))))
print("atan({0:f}) = {1:f}".format(math.tan(b), math.atan(math.tan(b))))
print("atan({0:f}) = {1:f}".format(math.tan(c), math.atan(math.tan(c))))
# 45 degrees
print("atan2({0:f}, {1:f}) = {2:f}".format(1.0, 1.0, math.atan2(1.0, 1.0)))
# 30 degrees
print("atan2({0:f}, {1:f}) = {2:f}".format(1.0, math.sqrt(3.0), math.atan2(1.0, math.sqrt(3.0))))
# sinh, cosh, tanh, atanh, acosh, asinh
print("sinh({0:f}) = {1:f}".format(a, math.sinh(a)))
print("sinh({0:f}) = {1:f}".format(b, math.sinh(b)))
print("sinh({0:f}) = {1:f}".format(c, math.sinh(c)))
print("sinh({0:f}) = {1:f}".format(d, math.sinh(d)))
print("cosh({0:f}) = {1:f}".format(a, math.cosh(a)))
print("cosh({0:f}) = {1:f}".format(b, math.cosh(b)))
print("cosh({0:f}) = {1:f}".format(c, math.cosh(c)))
print("cosh({0:f}) = {1:f}".format(d, math.cosh(d)))
print("tanh({0:f}) = {1:f}".format(a, math.tanh(a)))
print("tanh({0:f}) = {1:f}".format(b, math.tanh(b)))
print("tanh({0:f}) = {1:f}".format(c, math.tanh(c)))
print("tanh({0:f}) = {1:f}".format(d, math.tanh(d)))
print("asinh({0:f}) = {1:f}".format(math.sinh(a), math.asinh(math.sinh(a))))
print("asinh({0:f}) = {1:f}".format(math.sinh(b), math.asinh(math.sinh(b))))
print("asinh({0:f}) = {1:f}".format(math.sinh(c), math.asinh(math.sinh(c))))
print("asinh({0:f}) = {1:f}".format(math.sinh(d), math.asinh(math.sinh(d))))
print("acosh({0:f}) = {1:f}".format(math.cosh(a), math.acosh(math.cosh(a))))
print("acosh({0:f}) = {1:f}".format(math.cosh(b), math.acosh(math.cosh(b))))
print("acosh({0:f}) = {1:f}".format(math.cosh(c), math.acosh(math.cosh(c))))
print("acosh({0:f}) = {1:f}".format(math.cosh(d), math.acosh(math.cosh(d))))
print("atanh({0:f}) = {1:f}".format(math.tanh(a), math.atanh(math.tanh(a))))
print("atanh({0:f}) = {1:f}".format(math.tanh(b), math.atanh(math.tanh(b))))
print("atanh({0:f}) = {1:f}".format(math.tanh(c), math.atanh(math.tanh(c))))
print("atanh({0:f}) = {1:f}".format(math.tanh(d), math.atanh(math.tanh(d))))
# log, log10, exp, pow, sqrt
print("log({0:f}) = {1:f}".format(a, math.log(a)))
print("log({0:f}) = {1:f}".format(b, math.log(b)))
print("log({0:f}) = {1:f}".format(-c, math.log(-c)))
print("log({0:f}) = {1:f}".format(-d, math.log(-d)))
print("log({0:f}) = {1:f}".format(e, math.log(e)))
print("log10({0:f}) = {1:f}".format(a, math.log10(a)))
print("log10({0:f}) = {1:f}".format(b, math.log10(b)))
print("log10({0:f}) = {1:f}".format(-c, math.log10(-c)))
print("log10({0:f}) = {1:f}".format(-d, math.log10(-d)))
print("log10({0:f}) = {1:f}".format(e, math.log10(e)))
print("exp({0:f}) = {1:f}".format(0.5, math.exp(0.5)))
print("exp({0:f}) = {1:f}".format(1.0, math.exp(1.0)))
print("exp({0:f}) = {1:f}".format(2.0, math.exp(2.0)))
print("pow({0:f}, {1:f}) = {2:f}".format(10.0, 0.5, math.pow(10.0, 0.5)))
print("pow({0:f}, {1:f}) = {2:f}".format(10.0, 1.0, math.pow(10.0, 1.0)))
print("pow({0:f}, {1:f}) = {2:f}".format(10.0, 2.0, math.pow(10.0, 2.0)))
print("sqrt({0:f}) = {1:f}".format(0.5, math.sqrt(0.5)))
print("sqrt({0:f}) = {1:f}".format(2.0, math.sqrt(2.0)))
print("sqrt({0:f}) = {1:f}".format(10.0, math.sqrt(10.0)))
# random numbers
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
Output
The program below illustrates the use of the integer math and random number functions.
#!/usr/bin/env python3;
###############################################################################
# This program demonstrates the math integer functions.
#
# Copyright © 2020 Richard Lesh. All rights reserved.
###############################################################################
import Utils
import math
import random
# Begin Main
a = 5
b = 10
c = -2
# abs, floor, ceil, round, trunc, min, max
print("abs({0:d}) = {1:d}".format(a, abs(a)))
print("abs({0:d}) = {1:d}".format(c, abs(c)))
print("min({0:d}, {1:d}) = {2:d}".format(a, b, min(a, b)))
print("max({0:d}, {1:d}) = {2:d}".format(a, b, max(a, b)))
print("min({0:d}, {1:d}) = {2:d}".format(b, c, min(b, c)))
print("max({0:d}, {1:d}) = {2:d}".format(b, c, max(b, c)))
# random numbers
print("random({0:d}) = {1:d}".format(a, int(a * random.random())))
print("random({0:d}) = {1:d}".format(a, int(a * random.random())))
print("random({0:d}) = {1:d}".format(a, int(a * random.random())))
print("random({0:d}) = {1:d}".format(a, int(a * random.random())))
print("random({0:d}) = {1:d}".format(a, int(a * random.random())))
print("random({0:d}) = {1:d}".format(b, int(b * random.random())))
print("random({0:d}) = {1:d}".format(b, int(b * random.random())))
print("random({0:d}) = {1:d}".format(b, int(b * random.random())))
print("random({0:d}) = {1:d}".format(b, int(b * random.random())))
print("random({0:d}) = {1:d}".format(b, int(b * random.random())))
print("random(2) = {0:d}".format(int(2 * random.random())))
print("random(2) = {0:d}".format(int(2 * random.random())))
print("random(2) = {0:d}".format(int(2 * random.random())))
print("random(2) = {0:d}".format(int(2 * random.random())))
print("random(2) = {0:d}".format(int(2 * random.random())))
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
print("random() = {0:f}".format(random.random()))
Output
Random Numbers
Random number generation is an important technique needed for simulations and games. Computers can't actually generate true random numbers, so we have to settle for [[pseudorandom]] numbers, i.e. numbers generated deterministically but hopefully in an unpredictable manner.
In modern Python, random number generation is usually done with the random module from the standard library.
For the three most common cases of uniform integers, uniform floating point numbers, and normally distributed ([[Gaussian]]) floating point numbers, Python provides functions such as:
- uniform integers →
randint()orrandrange() - uniform floating point numbers →
random() - normal (Gaussian) floating point numbers →
gauss()ornormalvariate()
For our example program we generate 10 numbers from each of the three distributions. Notice how each time we run the program, we will usually get different values.
import random
print("Uniform integers in [1, 6]")
for i in range(10):
print(random.randint(1, 6))
print("Uniform floats in [0.0, 1.0)")
for i in range(10):
print(random.random())
print("Standard Normal")
for i in range(10):
print(random.gauss(0.0, 1.0))
Output
The uniform integer generator can produce integers uniformly in a range such as: [1, 6].
In Python, integer bounds are often expressed using inclusive endpoints. So to simulate a six-sided die we would write:
random.randint(1, 6).
This means both endpoints are included, so the possible values are 1 through 6. That makes it perfect for dice rolls, random indices, and similar cases.
The uniform floating point generator produces numbers uniformly in the range: [0.0, 1.0).
This means that only the low endpoint 0.0 is included. The high endpoint 1.0 will not be generated, i.e. low <= random < high. You can scale this output to another range [low, high) with the function:
random.uniform(low, high)
That is commonly used for probabilities, simulation, [[Monte Carlo Method]], and scaling into another range.
The Gaussian generator produces values from a normal distribution with mean = 0.0 and standard deviation = 1.0. That is called the standard normal distribution.
Most values cluster near the mean, and larger positive or negative values become less likely.
For example, to model exam scores centered around 75 with a standard deviation of 10, we can scale and shift the standard normal value like this: random.gauss(75.0, 10.0).
Deterministic vs Non-Deterministic Seeding
If you want the same random sequence every run, use a fixed seed such as 12345. This is useful for debugging and testing.
random.seed(12345)
If you want variation between runs, Python automatically seeds the generator when the program starts.
Whichever technique you choose, only seed the generator once. Do not recreate and re-seed it repeatedly in a loop.
Random Number Functions
The random module provides several useful functions:
random()→ floating point number in [0.0, 1.0)randint(a, b)→ integer in [a, b]randrange(a, b)→ integer in [a, b)gauss(mean, stddev)→ Gaussian distributionuniform(a, b)→ floating point number in [a, b]
Cryptographically Secure Random Numbers
For security-sensitive work such as tokens, passwords, or keys, do not use the standard random module.
Instead use the secrets module, which is designed for cryptographic use.
import secrets token = secrets.token_hex(16) print(token)
This produces much stronger random values suitable for security-related purposes.
Questions
- {{Write an expression that yields √5.}}
- {{Write an expression that yields 3√5.}}
- {{Write an expression that yields the secant of π/4.}}
- {{Write an expression that yields log16 100.}}
Projects
More ★'s indicate higher difficulty level.
References
- [[Python Language Reference]]
- [[Python Standard Library]]
- [[Python at TutorialsPoint]]
Pure Programmer


