import numpy as np

# range of values to investigate:
Nmax = 9

# Check if valid mathematical identity
#   a*(a/b) = (a*a)/b
# holds for small integer values of a and b
# Spoiler: It does not.
print( 'investigate identity   a*(a/b) = (a*a)/b:' )
for a in range( 1, Nmax+1 ):
    for b in range( 1, Nmax+1 ):
        if a*(a/b) != (a*a)/b:
           print ( a,'*(',a,'/',b,') != (',a,'*',a,')/', b, sep = '' )


# the same holds for e.g. square roots
# that is, for irational numbers:
print( 'square root precision: ')

import math
for a in range( 1, Nmax+1 ):
    if math.sqrt(a) * math.sqrt(a) != a:
       print( 'sqrt(',a,')*sqrt(',a,') != ', a )


# numpy behaves in analogous way

print( 'square root precision in numpy: ')
print( 'compute    sqrt(a)*sqrt(a) - a  ')

import numpy as np
integers =  np.array( np.arange( Nmax+1 )  )
sqrts = np.array( [ np.sqrt(k) for k in np.arange( Nmax+1 ) ]  )
print( sqrts * sqrts - integers)



input()


# ----------------------------------------------------------
# get acquainted with float limits
print( "float limits of particular float types" )

print( np.finfo(np.float16) )
print( np.finfo(np.float32) )
print( np.finfo(np.float64) )


# default float?

arr = np.empty( (3,4) )
print( "default float type:\n" )
print(  np.finfo(arr.dtype) )



'''
# want to peek into a float representation?

get bits
import struct
def binary(num):
    return ''.join('{:0>8b}'.format(c) for c in struct.pack('!f', num))
'''

