## Doing Math in Python

#### Numeric Data Types

There are two ways numbers are represented internally - integers and floating point numbers. Even though the numbers 1 and 1.0 have the same value their internal representation are very different.

Computations with integers are exact, whereas those that involve floating point numbers are not. The accuracy of a floating point computation depends on the precision of the numbers used. Greater the precision, the more accurate the result. But there is limit to the precision of floating numbers. The precision is limited to the number of bits used. 32-bit floating point numbers have lower precision than 64-bit numbers. There is also a limit to how big or how small a floating point number you can represent. For a 32-bit representation the range is (+/-) 3.4E38 and for 64-bit representation the range is (+/-) 1.8E308.

There is also a limit to the range of integers that you can represent. With 32 bits the range is -231 to (231 - 1). In mixed operations, those that involve both integers and floating numbers, integers are converted to floating point numbers and the computation performed. Careful: consider this expression: 3.5 + (6/4). The result is 4.5 and not 5.0 as you would expect because the (6/4) is computed as an integer division which truncates the fractional portion of the quotient.

For even larger integer numbers Python has a third numeric type called a long int. The long int is not restricted by the number of bits and can expand to the limit of the available memory. To indicate that a number should be represented as a long int append an upper case ( L ).

```  x = 12345678987654321L
```

You can explicitly convert numbers of one type to another with built-in functions that Python provides:

```  x = 123
y = float (x)    # y = 123.0

z = 34.89
w = int (z)      # w = 34

p = 75
q = long (p)     # q = 75L
```
Note that when you convert to int, the function truncates instead of rounding.

#### Math Library

There are lots of useful functions in the Math Library. To use this library the first statement in your program must be

```  import math
```
The Math Library not only has functions but also useful constants like π and e. To use the functions or the constants in your program you must apply the dot operator. The general syntax for usage is math.function() or math.constant. The table below gives just a subset of all the functions available.

Function Meaning
ceil (x) Return the ceiling of x as a float, the smallest integer value greater than or equal to x.
floor (x) Return the floor of x as a float, the largest integer value less than or equal to x.
exp (x) Return e**x.
log (x, base) Return the logarithm of x to the given base. If the base is not specified, return the natural logarithm of x (that is, the logarithm to base e).
log10 (x) Return the base-10 logarithm of x.
pow (x, y) Return x**y.
sqrt (x) Return the square root of x.
degrees (x) Converts angle x from radians to degrees.
radians (x) Converts angle x from degrees to radians.
sin (x) Return the sine of x radians.
cos (x) Return the cosine of x radians.
tan (x) Return the tangent of x radians.
asin (x) Return the arc sine of x, in radians.
acos (x) Return the arc cosine of x, in radians.
atan (x) Return the arc tangent of x, in radians.
hypot (x, y) Return the Euclidean norm, sqrt(x*x + y*y). This is the length of the vector from the origin to point (x, y).
pi The mathematical constant pi.
e The mathematical constant e.

#### Random Number Generation

There are computations that require you to generate random numbers. Python provides a pseudo random number generator. The word pseudo in this context means that the random number generator is deterministic and after a certain cycle of generating random numbers it starts repeating that cycle.

However, for most simple computations the pseudo random number generator works fine since the cycle length is extremely large. All of the random number generating functions comes in a module called random and has to be imported in the program to be used. Your first line of code should read:

```  import random
```
To use the functions you must use the dot operator. The general usage is random.function(). The table below gives a subset of the functions that are available in the random module.

Function Meaning
randrange (start, stop, step) Return a randomly selected element from range(start, stop, step).
randint (a, b) Return a random integer N such that a <= N = <= b.
choice (seq) Return a random element from the non-empty sequence seq.
shuffle (x) Shuffle the sequence x in place.
sample (population, k) Return a k length list of unique elements chosen from the population sequence. Used for random sampling without replacement.
random () Return the next random floating point number in the range [0.0, 1.0).
uniform (a, b) Return a random real number N such that a <= N < b.

Here are some examples of using the random number generator:

```  # Random float x in the range 0.0 <= x < 1.0
x = random.random()               # x = 0.386265456797

# Random integer in the range 7 to 23 inclusive
x = random.randint(7, 23)         # x = 18

# Random float x in the range -1.0 <= x < 1.0
x = random.uniform (-1.0, 1.0)     # x = -0.0742003025108

# Choose a random number from 1 to 100 that is divisible by 3
x = random.randrange(3, 100, 3)    # x = 30

# Choose a random element from a sequence
seq = ['a', 'e', 'i', 'o', 'u']
x = random.choice(seq)             # x = 'o'

# Choose 2 elements from a population
x = random.sample (seq, 2)         # x = ['u', 'e']

# Shuffle a sequence
random.shuffle (seq)               # seq = ['e', 'a', 'o', 'i', 'u']

```