# Python Basics¶

## Unit 3, Lecture 1¶

Numerical Methods and Statistics

#### Prof. Andrew White, Jan 30 2020¶

Suggested Reading

# Variables¶

A way of storing a number. You create a variable by assigning (=) an expression (right-hand-side) to a name (left-hand-side).

In :
x = 2
print(x)

2

In :
print(x * 4)

8

In :
x = x + 2
print(x)

4

In :
import math
x = math.cos(43)
print(x)

0.5551133015206257

In :
a = 2
a = a * b
b = 4

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-5-de5ed0aa3cf0> in <module>
1 a = 2
----> 2 a = a * b
3 b = 4

NameError: name 'b' is not defined

### Be careful¶

Just like you remember to save you documents, be sure to store what you want in your variables.

In :
x = 2
x * 2
print(x)

2


# Python String Formatting¶

What's the point of having variables if we can't tell anyone about them?!?!

In :
x = 4
print('This is the simple way of printing x', x)

This is the simple way of printing x 4

In :
y = 2.3
print('This is how we print x', x, 'and y', y, '. Notice spaces are inserted for us')

This is how we print x 4 and y 2.3 . Notice spaces are inserted for us

In :
print('What if I want to print y ({}) without spaces?'.format(y))

What if I want to print y (2.3) without spaces?

In :
z = 0.489349842432423829328933 * 10**32
print('{}'.format(z))

4.893498424324239e+31


# The 'Formatted' in String Formatting¶

By using special character inside the {} expression, we can modify how variables are output.

In :
print('What if I want to print x twice, like this {0:} {0:}, and y once, {1:}?'.format(x,y))

What if I want to print x twice, like this 4 4, and y once, 2.3?

In :
print('With a fixed precision (number of digits): {:.4}'.format(z))

With a fixed precision (number of digits): 4.893e+31

In :
print('Make it take up exactly 10 spaces: {:10.4}'.format(z))
print('Make it take up exactly 10 spaces: {:10.4}'.format(math.pi))
print('Make it take up exactly 10 spaces: {:10.4}'.format(z*math.pi))

Make it take up exactly 10 spaces:  4.893e+31
Make it take up exactly 10 spaces:      3.142
Make it take up exactly 10 spaces:  1.537e+32

In :
print('You can demand to show without scientific notation too: {:f}'.format(z))

You can demand to show without scientific notation too: 48934984243242387076283208040448.000000

In :
print('or demand to use scientific notation: {:e}'.format(math.pi))

or demand to use scientific notation: 3.141593e+00

In :
print('There are many more formatting tags, such as binary: {:b} and percentage: {:%}'.format(43, 0.23))

There are many more formatting tags, such as binary: 101011 and percentage: 23.000000%


# Representing Data¶

Consider a model where the computer uses 8 bit numbers (1 byte). You could represent $[0,2^8-1]$.

In :
%%bash
pip install fixedint

Requirement already satisfied: fixedint in /home/whitead/miniconda3/lib/python3.7/site-packages (0.1.5)

In :
from fixedint import *

def bprint(x):
print('{0:08b} ({0:})'.format(x))

In :
i = UInt8(8)
bprint(i)

00001000 (8)

In :
i = UInt8(24)
bprint(i)

00011000 (24)

In :
i = UInt8(2**8 - 1)
bprint(i)

11111111 (255)

In :
i = UInt8(2**8)
bprint(i)

00000000 (0)


This effect, where if we add 1 too many to a number and "roll-over" to the beginnig is called integer overflow. This is a common bug in programming, where a number becomes too large and then rolls-back.

Ineger overflow can result in negative numbers, if we have signed numbers.

In :
i = Int8(2**7 - 1)
bprint(i)
bprint(i + 1)

01111111 (127)
-10000000 (-128)


Notice here that our max is half previously, because one of our 8 bits is for sign, so only 7 bits are available for integers. The key takeaway from integer overflow is that if we have integers with not enough bytes, we can suddenly have negative numbers or zero when adding large numbers. Real world examples of integer overflow include view counts becoming 0, having data usage become negative on a cellphone, the Y2K bug, a step counter going to 0 steps.