#Jonathan Hudson
#Student Number 12347890
#Date: 2020-08-26
#Lecture Practice
# Topic 4: Information and Data
## Base 2 decimals
#A decimal number is a sum of values in 10s, 100s, 1000s and 1/10s, 1/100s, 1/1000s, etc
#Ex.
#1/8 in base 10
#0.125 base 10 = 1/10 + 2/100 + 5/1000 in base 10
#We can represent a binary decimal the same way
#2s, 4s, 8s, and 1/2s, 1/4s, 1/8s
#Ex.
#1/8 in base 2
#0.001 base 2 = 0/2 + 0/8 + 1/8
#Some numbers are not repeating in either base like 1/8
#However some are
#0.1 = 1/10 is non-repeating in base 10
#but is repeating in base 2
#You've done decimal approximation in the past. Often when you need to approximate a base 10 number you do
#1/3 = 0.33333..... repeating
#or use
#3/10 or 33/100 or 333/1000 for a level of accuracy
#However what is repeating in base 10 is not repeating in base 2
#1/10 which is not repeating in base 10 is repeating in base 2
#1/8 is not repeating in base 2 or base 10
#Converting 0.1 base 10 to base 2
#0.1 * 2 = 0.2 -> 0
#0.2 * 2 = 0.4 -> 0
#0.4 * 2 = 0.8 -> 0
#0.8 * 2 = 1.6 -> 1
#0.6 * 2 = 1.2 -> 1
#0.2 * 2 = 0.4 -> 0
# ... forever
#0.0001100110011001100... base 2
## Danger of repeating base 2 decimals
#Let's look at what is stored for some base 10 decimals in python
#print(1/10)
#print(1/8)
#"""Seems fine?"""
#print("%.50f" % (1/10))
#print("%.50f" % (1/8))
#Wait that's a lot of junk in the 1/10?
## Storing base 2 fractions (storing floating point numbers in python)
#We use binary fractions to represent floats
#var = 1/10
#Before garbage is seen
#print("%.16f" % var)
#Bit of garbage
#print("%.17f" % var)
#All the garbage
#print("%.55f" % var)
#"""I'm going to recreate that garbage filled float"""
#print("%.55f" % (3602879701896397 / 2 ** 55))
#"""How did I know that"""
#print(var.as_integer_ratio())
#Store a numerator (integer) using first 53 bits (1 is sign bit)
#Store a exponent (integer) using 11 bits
## What are the issues?
#Floating point error. This can really screw up your math program. Doing 'math class' is not doing the same as 'computing' math
#print(0.1+0.1+0.1)
#print(0.3)
#print("%.55f" % (0.1+0.1+0.1))
#print("%.55f" % (0.3))
#print(0.1+0.1+0.1 == 0.3)
#var1 = 0.1+0.1+0.1
#var2 = 0.3
#print(var1.as_integer_ratio())
#print(var2.as_integer_ratio())
#print(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)
#print("%.55f" % (0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1))
## Max representation sizes
#Integers
#import sys
#print(sys.maxsize)
##32 bit computer
#print(2**31-1)
##64 bit computer
#print(2**63-1)
#However if we overflow our int (integer) type then python uses a different storage structure to get a bigger size"""
#print(sys.maxsize+1)
#"""Floating points"""
#print("%.100f" % sys.float_info.max)
#print(sys.float_info.max.as_integer_ratio())
#"""Note if we get bigger from our max floating point that info just disappears"""
#print("%.100f" % (sys.float_info.max+1))
#print((sys.float_info.max== (sys.float_info.max+1)))
#print((sys.float_info.max== (sys.float_info.max+0.1)))
#print(sys.float_info.max.as_integer_ratio())
#print((sys.float_info.max+1).as_integer_ratio())