#!/usr/bin/env python
# coding: utf-8

# # Density of Floating Point Numbers
# 
# This notebook enumerates all possible floating point nubmers in a floating point system and shows them in a plot to illustrate their density.

# In[1]:


import matplotlib.pyplot as pt
import numpy as np


# In[2]:


significand_bits = 4
exponent_min = -3
exponent_max = 4

fp_numbers = []
for exp in range(exponent_min, exponent_max+1):
    for sbits in range(0, 2**significand_bits):
        significand = 1 + sbits/2**significand_bits 
        fp_numbers.append(significand * 2**exp)
        
fp_numbers = np.array(fp_numbers)
print(fp_numbers)

pt.plot(fp_numbers, np.ones_like(fp_numbers), "+")
#pt.semilogx(fp_numbers, np.ones_like(fp_numbers), "+")
        


# Relative gap size between consecutive floating point numbers. Notice that the maximum is achieved at $1$.

# In[3]:


pt.plot(
    np.abs(fp_numbers[1:]-fp_numbers[:-1])
    / np.abs(fp_numbers[:-1]))

n_one = int(np.argwhere(np.abs(fp_numbers-1) < 1e-12))
pt.plot([n_one], np.abs(fp_numbers[n_one+1] - fp_numbers[n_one]), 'r*')


# ## What about subnormals?

# In[4]:


subnormals = []
exp = exponent_min
for sbits in range(0, 2**significand_bits):
    significand = sbits / 2**significand_bits
    subnormals.append(significand * 2**exp)
subnormals = np.array(subnormals)

print(subnormals)
pt.plot(subnormals, np.ones_like(subnormals), "+")


# In[5]:


fnws = np.concatenate([subnormals, fp_numbers])

pt.plot(np.abs(fnws[1:]-fnws[:-1])/np.abs(fnws[:-1]))
pt.axvline(x=len(subnormals), color='r', linestyle='--')


# In[ ]:




