math – Mathematical functions

Purpose:Provides functions for specialized mathematical operations.
Available In:1.4

The math module implements many of the IEEE functions that would normally be found in the native platform C libraries for complex mathematical operations using floating point values, including logarithms and trigonometric operations.

Special Constants

Many math operations depend on special constants. math includes values for π (pi) and e.

import math

print 'π: %.30f' % math.pi
print 'e: %.30f' % math.e

Both values are limited in precision only by the platform’s floating point C library.

$ python math_constants.py

π: 3.141592653589793115997963468544
e: 2.718281828459045090795598298428

Testing for Exceptional Values

Floating point calculations can result in two types of exceptional values. INF (“infinity”) appears when the double used to hold a floating point value overflows from a value with a large absolute value.

import math

print '{:^3}  {:6}  {:6}  {:6}'.format('e', 'x', 'x**2', 'isinf')
print '{:-^3}  {:-^6}  {:-^6}  {:-^6}'.format('', '', '', '')

for e in range(0, 201, 20):
    x = 10.0 ** e
    y = x*x
    print '{:3d}  {!s:6}  {!s:6}  {!s:6}'.format(e, x, y, math.isinf(y))

When the exponent in this example grows large enough, the square of x no longer fits inside a double, and the value is recorded as infinite.

$ python math_isinf.py

 e   x       x**2    isinf
---  ------  ------  ------
  0  1.0     1.0     False
 20  1e+20   1e+40   False
 40  1e+40   1e+80   False
 60  1e+60   1e+120  False
 80  1e+80   1e+160  False
100  1e+100  1e+200  False
120  1e+120  1e+240  False
140  1e+140  1e+280  False
160  1e+160  inf     True
180  1e+180  inf     True
200  1e+200  inf     True

Not all floating point overflows result in INF values, however. Calculating an exponent with floating point values, in particular, raises OverflowError instead of preserving the INF result.

x = 10.0 ** 200

print 'x    =', x
print 'x*x  =', x*x
try:
    print 'x**2 =', x**2
except OverflowError, err:
    print err

This discrepancy is caused by an implementation difference in the library used by C Python.

$ python math_overflow.py

x    = 1e+200
x*x  = inf
x**2 = (34, 'Result too large')

Division operations using infinite values are undefined. The result of dividing a number by infinity is NaN (“not a number”).

import math

x = (10.0 ** 200) * (10.0 ** 200)
y = x/x

print 'x =', x
print 'isnan(x) =', math.isnan(x)
print 'y = x / x =', x/x
print 'y == nan =', y == float('nan')
print 'isnan(y) =', math.isnan(y)

NaN does not compare as equal to any value, even itself, so to check for NaN you must use isnan().

$ python math_isnan.py

x = inf
isnan(x) = False
y = x / x = nan
y == nan = False
isnan(y) = True

Converting to Integers

The math module includes three functions for converting floating point values to whole numbers. Each takes a different approach, and will be useful in different circumstances.

The simplest is trunc(), which truncates the digits following the decimal, leaving only the significant digits making up the whole number portion of the value. floor() converts its input to the largest preceding integer, and ceil() (ceiling) produces the largest integer following sequentially after the input value.

import math

print '{:^5}  {:^5}  {:^5}  {:^5}  {:^5}'.format('i', 'int', 'trunk', 'floor', 'ceil')
print '{:-^5}  {:-^5}  {:-^5}  {:-^5}  {:-^5}'.format('', '', '', '', '')

fmt = '  '.join(['{:5.1f}'] * 5)

for i in [ -1.5, -0.8, -0.5, -0.2, 0, 0.2, 0.5, 0.8, 1 ]:
    print fmt.format(i, int(i), math.trunc(i), math.floor(i), math.ceil(i))
    

trunc() is equivalent to converting to int directly.

$ python math_integers.py

  i     int   trunk  floor  ceil
-----  -----  -----  -----  -----
 -1.5   -1.0   -1.0   -2.0   -1.0
 -0.8    0.0    0.0   -1.0   -0.0
 -0.5    0.0    0.0   -1.0   -0.0
 -0.2    0.0    0.0   -1.0   -0.0
  0.0    0.0    0.0    0.0    0.0
  0.2    0.0    0.0    0.0    1.0
  0.5    0.0    0.0    0.0    1.0
  0.8    0.0    0.0    0.0    1.0
  1.0    1.0    1.0    1.0    1.0

Alternate Representations

modf() takes a single floating point number and returns a tuple containing the fractional and whole number parts of the input value.

import math

for i in range(6):
    print '{}/2 = {}'.format(i, math.modf(i/2.0))

Both numbers in the return value are floats.

$ python math_modf.py

0/2 = (0.0, 0.0)
1/2 = (0.5, 0.0)
2/2 = (0.0, 1.0)
3/2 = (0.5, 1.0)
4/2 = (0.0, 2.0)
5/2 = (0.5, 2.0)

frexp() returns the mantissa and exponent of a floating point number, and can be used to create a more portable representation of the value.

import math

print '{:^7}  {:^7}  {:^7}'.format('x', 'm', 'e')
print '{:-^7}  {:-^7}  {:-^7}'.format('', '', '')

for x in [ 0.1, 0.5, 4.0 ]:
    m, e = math.frexp(x)
    print '{:7.2f}  {:7.2f}  {:7d}'.format(x, m, e)

frexp() uses the formula x = m * 2**e, and returns the values m and e.

$ python math_frexp.py

   x        m        e
-------  -------  -------
   0.10     0.80       -3
   0.50     0.50        0
   4.00     0.50        3

ldexp() is the inverse of frexp().

import math

print '{:^7}  {:^7}  {:^7}'.format('m', 'e', 'x')
print '{:-^7}  {:-^7}  {:-^7}'.format('', '', '')

for m, e in [ (0.8, -3),
              (0.5,  0),
              (0.5,  3),
              ]:
    x = math.ldexp(m, e)
    print '{:7.2f}  {:7d}  {:7.2f}'.format(m, e, x)

Using the same formula as frexp(), ldexp() takes the mantissa and exponent values as arguments and returns a floating point number.

$ python math_ldexp.py

   m        e        x
-------  -------  -------
   0.80       -3     0.10
   0.50        0     0.50
   0.50        3     4.00

Positive and Negative Signs

The absolute value of number is its value without a sign. Use fabs() to calculate the absolute value of a floating point number.

import math

print math.fabs(-1.1)
print math.fabs(-0.0)
print math.fabs(0.0)
print math.fabs(1.1)

In practical terms, the absolute value of a float is represented as a positive value.

$ python math_fabs.py

1.1
0.0
0.0
1.1

To determine the sign of a value, either to give a set of values the same sign or simply for comparison, use copysign() to set the sign of a known good value.

import math

print
print '{:^5}  {:^5}  {:^5}  {:^5}  {:^5}'.format('f', 's', '< 0', '> 0', '= 0')
print '{:-^5}  {:-^5}  {:-^5}  {:-^5}  {:-^5}'.format('', '', '', '', '')

for f in [ -1.0,
            0.0,
            1.0,
            float('-inf'),
            float('inf'),
            float('-nan'),
            float('nan'),
            ]:
    s = int(math.copysign(1, f))
    print '{:5.1f}  {:5d}  {!s:5}  {!s:5}  {!s:5}'.format(f, s, f < 0, f > 0, f==0)

An extra function like copysign() is needed because comparing NaN and -NaN directly with other values does not work.

$ python math_copysign.py


  f      s     < 0    > 0    = 0
-----  -----  -----  -----  -----
 -1.0     -1  True   False  False
  0.0      1  False  False  True
  1.0      1  False  True   False
 -inf     -1  True   False  False
  inf      1  False  True   False
  nan     -1  False  False  False
  nan      1  False  False  False

Commonly Used Calculations

Representing precise values in binary floating point memory is challenging. Some values cannot be represented exactly, and the more often a value is manipulated through repeated calculations, the more likely a representation error will be introduced. math includes a function for computing the sum of a series of floating point numbers using an efficient algorithm that minimize such errors.

import math

values = [ 0.1 ] * 10

print 'Input values:', values

print 'sum()       : {:.20f}'.format(sum(values))

s = 0.0
for i in values:
    s += i
print 'for-loop    : {:.20f}'.format(s)
    
print 'math.fsum() : {:.20f}'.format(math.fsum(values))

Given a sequence of ten values each equal to 0.1, the expected value for the sum of the sequence is 1.0. Since 0.1 cannot be represented exactly as a floating point value, however, errors are introduced into the sum unless it is calculated with fsum().

$ python math_fsum.py

Input values: [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
sum()       : 0.99999999999999988898
for-loop    : 0.99999999999999988898
math.fsum() : 1.00000000000000000000

factorial() is commonly used to calculate the number of permutations and combinations of a series of objects. The factorial of a positive integer n, expressed n!, is defined recursively as (n-1)! * n and stops with 0! == 1.

import math

for i in [ 0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.1 ]:
    try:
        print '{:2.0f}  {:6.0f}'.format(i, math.factorial(i))
    except ValueError, err:
        print 'Error computing factorial(%s):' % i, err

factorial() only works with whole numbers, but does accept float arguments as long as they can be converted to an integer without losing value.

$ python math_factorial.py

 0       1
 1       1
 2       2
 3       6
 4      24
 5     120
Error computing factorial(6.1): factorial() only accepts integral values

gamma() is like factorial(), except it works with real numbers and the value is shifted down one (gamma is equal to (n - 1)!).

import math

for i in [ 0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 ]:
    try:
        print '{:2.1f}  {:6.2f}'.format(i, math.gamma(i))
    except ValueError, err:
        print 'Error computing gamma(%s):' % i, err

Since zero causes the start value to be negative, it is not allowed.

$ python math_gamma.py

Error computing gamma(0): math domain error
1.1    0.95
2.2    1.10
3.3    2.68
4.4   10.14
5.5   52.34
6.6  344.70

lgamma() returns the natural logarithm of the absolute value of Gamma for the input value.

import math

for i in [ 0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 ]:
    try:
        print '{:2.1f}  {:.20f}  {:.20f}'.format(i, math.lgamma(i), math.log(math.gamma(i)))
    except ValueError, err:
        print 'Error computing lgamma(%s):' % i, err

Using lgamma() retains more precision than calculating the logarithm separately using the results of gamma().

$ python math_lgamma.py

Error computing lgamma(0): math domain error
1.1  -0.04987244125984036103  -0.04987244125983997245
2.2  0.09694746679063825923  0.09694746679063866168
3.3  0.98709857789473387513  0.98709857789473409717
4.4  2.31610349142485727469  2.31610349142485727469
5.5  3.95781396761871651080  3.95781396761871606671
6.6  5.84268005527463252236  5.84268005527463252236

The modulo operator (%) computes the remainder of a division expression (i.e., 5 % 2 = 1). The operator built into the language works well with integers but, as with so many other floating point operations, intermediate calculations cause representational issues that result in a loss of data. fmod() provides a more accurate implementation for floating point values.

import math

print '{:^4}  {:^4}  {:^5}  {:^5}'.format('x', 'y', '%', 'fmod')
print '----  ----  -----  -----'

for x, y in [ (5, 2),
              (5, -2),
              (-5, 2),
              ]:
    print '{:4.1f}  {:4.1f}  {:5.2f}  {:5.2f}'.format(x, y, x % y, math.fmod(x, y))

A potentially more frequent source of confusion is the fact that the algorithm used by fmod for computing modulo is also different from that used by %, so the sign of the result is different. mixed-sign inputs.

$ python math_fmod.py

 x     y      %    fmod
----  ----  -----  -----
 5.0   2.0   1.00   1.00
 5.0  -2.0  -1.00   1.00
-5.0   2.0   1.00  -1.00

Exponents and Logarithms

Exponential growth curves appear in economics, physics, and other sciences. Python has a built-in exponentiation operator (“**”), but pow() can be useful when you need to pass a callable function as an argument.

import math

for x, y in [
    # Typical uses
    (2, 3),
    (2.1, 3.2),

    # Always 1
    (1.0, 5),
    (2.0, 0),

    # Not-a-number
    (2, float('nan')),

    # Roots
    (9.0, 0.5),
    (27.0, 1.0/3),
    ]:
    print '{:5.1f} ** {:5.3f} = {:6.3f}'.format(x, y, math.pow(x, y))

Raising 1 to any power always returns 1.0, as does raising any value to a power of 0.0. Most operations on the not-a-number value nan return nan. If the exponent is less than 1, pow() computes a root.

$ python math_pow.py

  2.0 ** 3.000 =  8.000
  2.1 ** 3.200 = 10.742
  1.0 ** 5.000 =  1.000
  2.0 ** 0.000 =  1.000
  2.0 **   nan =    nan
  9.0 ** 0.500 =  3.000
 27.0 ** 0.333 =  3.000

Since square roots (exponent of 1/2) are used so frequently, there is a separate function for computing them.

import math

print math.sqrt(9.0)
print math.sqrt(3)
try:
    print math.sqrt(-1)
except ValueError, err:
    print 'Cannot compute sqrt(-1):', err
    

Computing the square roots of negative numbers requires complex numbers, which are not handled by math. Any attempt to calculate a square root of a negative value results in a ValueError.

$ python math_sqrt.py

3.0
1.73205080757
Cannot compute sqrt(-1): math domain error

The logarithm function finds y where x = b ** y. By default, log() computes the natural logarithm (the base is e). If a second argument is provided, that value is used as the base.

import math

print math.log(8)
print math.log(8, 2)
print math.log(0.5, 2)

Logarithms where x is less than one yield negative results.

$ python math_log.py

2.07944154168
3.0
-1.0

There are two variations of log(). Given floating point representation and rounding errors the computed value produced by log(x, b) has limited accuracy, especially for some bases. log10() computes log(x, 10), using a more accurate algorithm than log().

import math

print '{:2}  {:^12}  {:^20}  {:^20}  {:8}'.format('i', 'x', 'accurate', 'inaccurate', 'mismatch')
print '{:-^2}  {:-^12}  {:-^20}  {:-^20}  {:-^8}'.format('', '', '', '', '')

for i in range(0, 10):
    x = math.pow(10, i)
    accurate = math.log10(x)
    inaccurate = math.log(x, 10)
    match = '' if int(inaccurate) == i else '*'
    print '{:2d}  {:12.1f}  {:20.18f}  {:20.18f}  {:^5}'.format(i, x, accurate, inaccurate, match)

The lines in the output with trailing * highlight the inaccurate values.

$ python math_log10.py

i        x              accurate             inaccurate       mismatch
--  ------------  --------------------  --------------------  --------
 0           1.0  0.000000000000000000  0.000000000000000000
 1          10.0  1.000000000000000000  1.000000000000000000
 2         100.0  2.000000000000000000  2.000000000000000000
 3        1000.0  3.000000000000000000  2.999999999999999556    *
 4       10000.0  4.000000000000000000  4.000000000000000000
 5      100000.0  5.000000000000000000  5.000000000000000000
 6     1000000.0  6.000000000000000000  5.999999999999999112    *
 7    10000000.0  7.000000000000000000  7.000000000000000000
 8   100000000.0  8.000000000000000000  8.000000000000000000
 9  1000000000.0  9.000000000000000000  8.999999999999998224    *

log1p() calculates the Newton-Mercator series (the natural logarithm of 1+x).

import math

x = 0.0000000000000000000000001
print 'x       :', x
print '1 + x   :', 1+x
print 'log(1+x):', math.log(1+x)
print 'log1p(x):', math.log1p(x)

log1p() is more accurate for values of x very close to zero because it uses an algorithm that compensates for round-off errors from the initial addition.

$ python math_log1p.py

x       : 1e-25
1 + x   : 1.0
log(1+x): 0.0
log1p(x): 1e-25

exp() computes the exponential function (e**x).

import math

x = 2

fmt = '%.20f'
print fmt % (math.e ** 2)
print fmt % math.pow(math.e, 2)
print fmt % math.exp(2)

As with other special-case functions, it uses an algorithm that produces more accurate results than the general-purpose equivalent math.pow(math.e, x).

$ python math_exp.py

7.38905609893064951876
7.38905609893064951876
7.38905609893065040694

expm1() is the inverse of log1p(), and calculates e**x - 1.

import math

x = 0.0000000000000000000000001

print x
print math.exp(x) - 1
print math.expm1(x)

As with log1p(), small values of x lose precision when the subtraction is performed separately.

$ python math_expm1.py

1e-25
0.0
1e-25

Angles

Although degrees are more commonly used in everyday discussions of angles, radians are the standard unit of angular measure in science and math. A radian is the angle created by two lines intersecting at the center of a circle, with their ends on the circumference of the circle spaced one radius apart.

The circumference is calculated as 2πr, so there is a relationship between radians and π, a value that shows up frequently in trigonometric calculations. That relationship leads to radians being used in trigonometry and calculus, because they result in more compact formulas.

To convert from degrees to radians, use radians().

import math

print '{:^7}  {:^7}  {:^7}'.format('Degrees', 'Radians', 'Expected')
print '{:-^7}  {:-^7}  {:-^7}'.format('', '', '')

for deg, expected in [ (  0,  0),
                       ( 30,  math.pi/6),
                       ( 45,  math.pi/4),
                       ( 60,  math.pi/3),
                       ( 90,  math.pi/2),
                       (180,  math.pi),
                       (270,  3/2.0 * math.pi),
                       (360,  2 * math.pi),
                       ]:
    print '{:7d}  {:7.2f}  {:7.2f}'.format(deg, math.radians(deg), expected)

The formula for the conversion is rad = deg * π / 180.

$ python math_radians.py

Degrees  Radians  Expected
-------  -------  -------
      0     0.00     0.00
     30     0.52     0.52
     45     0.79     0.79
     60     1.05     1.05
     90     1.57     1.57
    180     3.14     3.14
    270     4.71     4.71
    360     6.28     6.28

To convert from radians to degrees, use degrees().

import math

print '{:^8}  {:^8}  {:^8}'.format('Radians', 'Degrees', 'Expected')
print '{:-^8}  {:-^8}  {:-^8}'.format('', '', '')
for rad, expected in [ (0,                  0),
                       (math.pi/6,         30),
                       (math.pi/4,         45),
                       (math.pi/3,         60),
                       (math.pi/2,         90),
                       (math.pi,          180),
                       (3 * math.pi / 2,  270),
                       (2 * math.pi,      360),
                       ]:
    print '{:8.2f}  {:8.2f}  {:8.2f}'.format(rad, math.degrees(rad), expected)

The formula is deg = rad * 180 / π.

$ python math_degrees.py

Radians   Degrees   Expected
--------  --------  --------
    0.00      0.00      0.00
    0.52     30.00     30.00
    0.79     45.00     45.00
    1.05     60.00     60.00
    1.57     90.00     90.00
    3.14    180.00    180.00
    4.71    270.00    270.00
    6.28    360.00    360.00

Trigonometry

Trigonometric functions relate angles in a triangle to the lengths of its sides. They show up in formulas with periodic properties such as harmonics, circular motion, or when dealing with angles.

Note

All of the trigonometric functions in the standard library take angles expressed as radians.

Given an angle in a right triangle, the sine is the ratio of the length of the side opposite the angle to the hypotenuse (sin A = opposite/hypotenuse). The cosine is the ratio of the length of the adjacent side to the hypotenuse (cos A = adjacent/hypotenuse). And the tangent is the ratio of the opposite side to the adjacent side (tan A = opposite/adjacent).

import math

print 'Degrees  Radians  Sine     Cosine    Tangent'
print '-------  -------  -------  --------  -------'

fmt = '  '.join(['%7.2f'] * 5)

for deg in range(0, 361, 30):
    rad = math.radians(deg)
    if deg in (90, 270):
        t = float('inf')
    else:
        t = math.tan(rad)
    print fmt % (deg, rad, math.sin(rad), math.cos(rad), t)

The tangent can also be defined as the ratio of the sine of the angle to its cosine, and since the cosine is 0 for π/2 and 3π/2 radians, the tangent is infinite.

$ python math_trig.py

Degrees  Radians  Sine     Cosine    Tangent
-------  -------  -------  --------  -------
   0.00     0.00     0.00     1.00     0.00
  30.00     0.52     0.50     0.87     0.58
  60.00     1.05     0.87     0.50     1.73
  90.00     1.57     1.00     0.00      inf
 120.00     2.09     0.87    -0.50    -1.73
 150.00     2.62     0.50    -0.87    -0.58
 180.00     3.14     0.00    -1.00    -0.00
 210.00     3.67    -0.50    -0.87     0.58
 240.00     4.19    -0.87    -0.50     1.73
 270.00     4.71    -1.00    -0.00      inf
 300.00     5.24    -0.87     0.50    -1.73
 330.00     5.76    -0.50     0.87    -0.58
 360.00     6.28    -0.00     1.00    -0.00

Given a point (x, y), the length of the hypotenuse for the triangle between the points [(0, 0), (x, 0), (x, y)] is (x**2 + y**2) ** 1/2, and can be computed with hypot().

import math

print '{:^7}  {:^7}  {:^10}'.format('X', 'Y', 'Hypotenuse')
print '{:-^7}  {:-^7}  {:-^10}'.format('', '', '')

for x, y in [ # simple points
              (1, 1),
              (-1, -1),
              (math.sqrt(2), math.sqrt(2)),
              (3, 4), # 3-4-5 triangle
              # on the circle
              (math.sqrt(2)/2, math.sqrt(2)/2), # pi/4 rads
              (0.5, math.sqrt(3)/2), # pi/3 rads
              ]:
    h = math.hypot(x, y)
    print '{:7.2f}  {:7.2f}  {:7.2f}'.format(x, y, h)

Points on the circle always have hypotenuse == 1.

$ python math_hypot.py

   X        Y     Hypotenuse
-------  -------  ----------
   1.00     1.00     1.41
  -1.00    -1.00     1.41
   1.41     1.41     2.00
   3.00     4.00     5.00
   0.71     0.71     1.00
   0.50     0.87     1.00

The same function can be used to find the distance between two points.

import math

print '{:^8}  {:^8}  {:^8}  {:^8}  {:^8}'.format('X1', 'Y1', 'X2', 'Y2', 'Distance')
print '{:-^8}  {:-^8}  {:-^8}  {:-^8}  {:-^8}'.format('', '', '', '', '')


for (x1, y1), (x2, y2) in [ ((5, 5), (6, 6)),
                            ((-6, -6), (-5, -5)),
                            ((0, 0), (3, 4)), # 3-4-5 triangle
                            ((-1, -1), (2, 3)), # 3-4-5 triangle
                            ]:
    x = x1 - x2
    y = y1 - y2
    h = math.hypot(x, y)
    print '{:8.2f}  {:8.2f}  {:8.2f}  {:8.2f}  {:8.2f}'.format(x1, y1, x2, y2, h)

Use the difference in the x and y values to move one endpoint to the origin, and then pass the results to hypot().

$ python math_distance_2_points.py

   X1        Y1        X2        Y2     Distance
--------  --------  --------  --------  --------
    5.00      5.00      6.00      6.00      1.41
   -6.00     -6.00     -5.00     -5.00      1.41
    0.00      0.00      3.00      4.00      5.00
   -1.00     -1.00      2.00      3.00      5.00

math also defines inverse trigonometric functions.

import math

for r in [ 0, 0.5, 1 ]:
    print 'arcsine(%.1f)    = %5.2f' % (r, math.asin(r))
    print 'arccosine(%.1f)  = %5.2f' % (r, math.acos(r))
    print 'arctangent(%.1f) = %5.2f' % (r, math.atan(r))
    print

1.57 is roughly equal to π/2, or 90 degrees, the angle at which the sine is 1 and the cosine is 0.

$ python math_inverse_trig.py

arcsine(0.0)    =  0.00
arccosine(0.0)  =  1.57
arctangent(0.0) =  0.00

arcsine(0.5)    =  0.52
arccosine(0.5)  =  1.05
arctangent(0.5) =  0.46

arcsine(1.0)    =  1.57
arccosine(1.0)  =  0.00
arctangent(1.0) =  0.79

Hyperbolic Functions

Hyperbolic functions appear in linear differential equations and are used when working with electromagnetic fields, fluid dynamics, special relativity, and other advanced physics and mathematics.

import math

print '{:^6}  {:^6}  {:^6}  {:^6}'.format('X', 'sinh', 'cosh', 'tanh')
print '{:-^6}  {:-^6}  {:-^6}  {:-^6}'.format('', '', '', '')

fmt = '  '.join(['{:6.4f}'] * 4)

for i in range(0, 11, 2):
    x = i/10.0
    print fmt.format(x, math.sinh(x), math.cosh(x), math.tanh(x))
    

Whereas the cosine and sine functions enscribe a circle, the hyperbolic cosine and hyperbolic sine form half of a hyperbola.

$ python math_hyperbolic.py

  X      sinh    cosh    tanh
------  ------  ------  ------
0.0000  0.0000  1.0000  0.0000
0.2000  0.2013  1.0201  0.1974
0.4000  0.4108  1.0811  0.3799
0.6000  0.6367  1.1855  0.5370
0.8000  0.8881  1.3374  0.6640
1.0000  1.1752  1.5431  0.7616

Inverse hyperbolic functions acosh(), asinh(), and atanh() are also available.

Special Functions

The Gauss Error function is used in statistics.

import math

print '{:^5}  {:7}'.format('x', 'erf(x)')
print '{:-^5}  {:-^7}'.format('', '')

for x in [ -3, -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2, 3 ]:
    print '{:5.2f}  {:7.4f}'.format(x, math.erf(x))
    

Notice that erf(-x) == -erf(x).

$ python math_erf.py

  x    erf(x)
-----  -------
-3.00  -1.0000
-2.00  -0.9953
-1.00  -0.8427
-0.50  -0.5205
-0.25  -0.2763
 0.00   0.0000
 0.25   0.2763
 0.50   0.5205
 1.00   0.8427
 2.00   0.9953
 3.00   1.0000

The complimentary error function is 1 - erf(x).

import math

print '{:^5}  {:7}'.format('x', 'erfc(x)')
print '{:-^5}  {:-^7}'.format('', '')

for x in [ -3, -2, -1, -0.5, -0.25, 0, 0.25, 0.5, 1, 2, 3 ]:
    print '{:5.2f}  {:7.4f}'.format(x, math.erfc(x))
    
$ python math_erfc.py

  x    erfc(x)
-----  -------
-3.00   2.0000
-2.00   1.9953
-1.00   1.8427
-0.50   1.5205
-0.25   1.2763
 0.00   1.0000
 0.25   0.7237
 0.50   0.4795
 1.00   0.1573
 2.00   0.0047
 3.00   0.0000

See also

math
The standard library documentation for this module.
IEEE floating point arithmetic in Python
Blog post by John Cook about how special values arise and are dealt with when doing math in Python.
SciPy
Open source libraryes for scientific and mathematical calculations in Python.