Floating point numbers are represented with a mantissa and exponent: $$\underbrace{0.3423}_{\textrm{mantissa}}\times{}\underbrace{10^{-2}}_{\textrm{exponent}}$$
We are working with computers though, so the mantissa is a binary and the exponent is in powers of 2. Let's look at them as decimals to begin though.
from IPython.display import Math
from math import frexp, pi
import math
#Convert a float into its mantissa and exponent and print as LaTeX
def fprint(x):
m,e = frexp(x)
return Math('{:4} \\times 2^{{{:}}}'.format(m, int(e)))
#Convert a mantissa from decimal to binary and print as LaTeX
def ffrac_ltx(x, terms=10):
bits = []
exp = 1
latex = ''
while x > 0 and exp < terms:
bits.append(int(x / 2.0 ** -exp))
x -= bits[-1] * 2.0 ** -exp
latex += '\\frac{{ {} }}{{ 2^{{ {} }} }} + '.format(bits[-1], exp)
exp += 1
return Math(latex[:-3] + ' = {}'.format(sum([b * 2**-i for b,i in zip(bits,range(1,exp))])))
def ffrac(x, terms=10):
bits = []
exp = 1
while x > 0 and exp < terms:
bits.append(int(x / 2.0 ** -exp))
x -= bits[-1] * 2.0 ** -exp
exp += 1
return ''.join(['{}'.format(x) for x in bits])
fprint(4.3)
fprint(0.1)
fprint(pi)
A 'decimal' in binary is challenging to think about, because each integer location is a $1 / 2^{n}$, where $n$ is the location. That means to represent a binary-mantissa exacly, its denominator must be a power of $2$. For example:
ffrac_ltx(0.5)
ffrac_ltx(0.75)
ffrac_ltx(0.5232)
#This is the maximum number of bits used in the 0.1 Mantissa as a string.
print(ffrac(0.1, 100))
0001100110011001100110011001100110011001100110011001101
print('{:0.28f}'.format(0.1))
0.1000000000000000055511151231
0.1 + 0.2 == (1.0 + 2.0) / 10.0
False
==
with floats!¶print(abs(-43))
43
x = -5
x = abs(x)
print(x)
5
Try typing math.fa
and hit TAB in ipython notebook. You should see suggestions. Next, type math.fabs(
and hit TAB and ipython notebook will tell you what the function does.
from math import fabs
print(fabs(-4.34322))
4.34322
from math import fabs, sin, cos
print(fabs(sin(4) * cos(43.)))
0.4201111317694318
from math import *
print(e)
2.718281828459045
print(2 == 5)
False
a = 3
print(a == 3)
True
print(a <= 0)
False
print(a > 0 and a < 4)
True
Boolean Logic uses Short-Circuiting - only as much as necessary is evaluated.
print(True or 1 / 0.)
True
print(True and 1 / 0.)
--------------------------------------------------------------------------- ZeroDivisionError Traceback (most recent call last) <ipython-input-21-8b897adc5aff> in <module> ----> 1 print(True and 1 / 0.) ZeroDivisionError: float division by zero
You can make code only accessible if a condition is true with if
. You can also use else
and elif
for alternatives.
To indicate where your if
code is located, press tab (which adds 4 spaces).
x = 65
if x > 43:
print('Surprise! {} is greater than 43'.format(x))
Surprise! 65 is greater than 43
x = 54
if x < 0:
print('{} is negative'.format(x))
elif x > 0:
print('{} is positive'.format(x))
else:
print('{} is 0'.format(x))
54 is positive
x = -32
if x < 0:
if abs(x) > 5:
print('{} is less than 0 and has magnitude greater than 5'.format(x))
else:
print('{} is not interesting'.format(x))
#or you can do:
if x < 0 and abs(x) > 5:
print('{} is less than 0 and has magnitude greater than 5'.format(x))
if x < 0 and not abs(x) > 5:
print('{} is not interesting'.format(x))
-32 is less than 0 and has magnitude greater than 5 -32 is less than 0 and has magnitude greater than 5
Here are the boolean operators: >
, <
, >=
, <=
, ==
, !=
, is
Recall our keywords from Lecture 1: and
, or
, and not
is
is used to see if a variables is None
or if two variables point to the same memory address.
a = 28238
b = 28238
print(a is b, a == b)
False True
a = b
print(a is b)
True
is None
is special case. None
is used as a "sentinel" value to indicate if something is not ready or invalid.
var = None
print(var is None)
True
a = 43
b = 23
print(a != b)
True
Just to be aware of, Python has a way of checking if an object is False
based on its value (0
or None
).
x = 1
if(x):
print('True')
else:
print('False')
True
x = None
if(x):
print('True')
else:
print('False')
False
x = 'Hello'
if(x):
print('True')
else:
print('False')
True
x = ''
if(x):
print('True')
else:
print('False')
False
x = math.sin(0.0)
if(x):
print('True')
else:
print('False')
False
It is better to just be explicit and give a full boolean expression. You'll most often see these used by accident
x = 0.15 + 0.15
y = 0.1 + 0.2
print(x == y)
False
Only use <
, >
. Never use ==
with boolean
x = 0.15 + 0.15
y = 0.1 + 0.2
abs(x - y) < 10**-8
True
In python, groups of values can be stored together into lists, which are like groups of variables.
numbers = [4,7,24,11,2]
print(numbers)
[4, 7, 24, 11, 2]
Individual elements can be accessed with []
. The thing that goes inside the brackets is called the index. Recall that python starts counting from 0
print(numbers[0], numbers[1])
4 7
You can access multiple elements with the :
symbol, which is called slicing.
print(numbers[0:3])
[4, 7, 24]
The last element to the slice operator is not inclusive, so 0:3
means 0, 1, 2. Why? Becuase you expect $3 - 0$ elements, which is three, starting from the $0$ index.
numbers[2:5]
[24, 11, 2]
If it's more convienent, you can count backwards from the end of the list by using negative indices. The trick is that -0
is not really a thing, so the last element in the list is -1
.
print(numbers)
print(numbers[-1], numbers[-2])
[4, 7, 24, 11, 2] 2 11
The index arguments to a slice are optional.
print(numbers[:4])
[4, 7, 24, 11]
print(numbers)
print(numbers[:-1])
[4, 7, 24, 11, 2] [4, 7, 24, 11]
print(numbers[3:])
[11, 2]
print(numbers[-3:])
[24, 11, 2]
You can add a third argument by adding another :
It is the step-size.
print(numbers)
print(numbers[0:-1:2])
[4, 7, 24, 11, 2] [4, 24]
The other slicing indices are optional.
print(numbers[0::2])
[4, 24, 2]
print(numbers)
print(numbers[::2])
[4, 7, 24, 11, 2] [4, 24, 2]
print(numbers[2::2])
[24, 2]
Using a negative stepsize allows you to count downwards
print(numbers[4:0:-1])
[2, 11, 24, 7]
Note that we still include the first slice index (4
), but not the second one (0
).
A common idiom is to reverse the order of list this way:
print(numbers, numbers[::-1])
[4, 7, 24, 11, 2] [2, 11, 24, 7, 4]
Notice that Python was clever and knew with a step-size of -1
, we actually wanted to start at the far end and count downwards.
Generally, most functions (like cos
) do not take a list. One common function that we need is len
, which returns the length of a list.
x = range(100)
len(x)
100
x = range(10)
print(max(x))
9
import math
math.cos(x)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-53-87cdf88e21ce> in <module> 1 import math ----> 2 math.cos(x) TypeError: must be real number, not range