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), "+")
        
[ 0.125      0.1328125  0.140625   0.1484375  0.15625    0.1640625
  0.171875   0.1796875  0.1875     0.1953125  0.203125   0.2109375
  0.21875    0.2265625  0.234375   0.2421875  0.25       0.265625
  0.28125    0.296875   0.3125     0.328125   0.34375    0.359375
  0.375      0.390625   0.40625    0.421875   0.4375     0.453125
  0.46875    0.484375   0.5        0.53125    0.5625     0.59375
  0.625      0.65625    0.6875     0.71875    0.75       0.78125
  0.8125     0.84375    0.875      0.90625    0.9375     0.96875
  1.         1.0625     1.125      1.1875     1.25       1.3125
  1.375      1.4375     1.5        1.5625     1.625      1.6875
  1.75       1.8125     1.875      1.9375     2.         2.125
  2.25       2.375      2.5        2.625      2.75       2.875
  3.         3.125      3.25       3.375      3.5        3.625
  3.75       3.875      4.         4.25       4.5        4.75
  5.         5.25       5.5        5.75       6.         6.25
  6.5        6.75       7.         7.25       7.5        7.75
  8.         8.5        9.         9.5       10.        10.5
 11.        11.5       12.        12.5       13.        13.5
 14.        14.5       15.        15.5       16.        17.
 18.        19.        20.        21.        22.        23.
 24.        25.        26.        27.        28.        29.
 30.        31.       ]
Out[2]:
[<matplotlib.lines.Line2D at 0x7fcb7872a790>]
No description has been provided for this image

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*')
Out[3]:
[<matplotlib.lines.Line2D at 0x7fcb7862bac0>]
No description has been provided for this image

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), "+")
[0.        0.0078125 0.015625  0.0234375 0.03125   0.0390625 0.046875
 0.0546875 0.0625    0.0703125 0.078125  0.0859375 0.09375   0.1015625
 0.109375  0.1171875]
Out[4]:
[<matplotlib.lines.Line2D at 0x7fcb7861e910>]
No description has been provided for this image
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='--')
/tmp/ipykernel_64778/473821165.py:3: RuntimeWarning: divide by zero encountered in true_divide
  pt.plot(np.abs(fnws[1:]-fnws[:-1])/np.abs(fnws[:-1]))
Out[5]:
<matplotlib.lines.Line2D at 0x7fcb785ccca0>
No description has been provided for this image
In [ ]: