import numpy as np
import matplotlib.pyplot as plt
from matplotlib import ticker
from scipy.stats import gaussian_kde
from lyceum.repr import bin2float
# On limite les points pour y voir quelquechose
NBITS = 7
EXPOSANT=3
MANTISSE=3
x_list= [i for i in range(2**NBITS)]
N = len(x_list)
x = np.array(x_list)
x_bin = np.array([format(i, f'0{NBITS}b') for i in x])
y = np.array([bin2float(i, e=EXPOSANT, f=MANTISSE) for i in x_bin])
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
# Sort the points by density, so that the densest points are plotted last
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
fig, ax = plt.subplots()
im = ax.scatter(x, y, marker='+', c=z, s=100, alpha=0.5)
xs = [i for i in x_list if 10*i % 2**(NBITS-2) == 0] + [2**(NBITS)-1]
x_labels = [format(i, f'0{NBITS}b') for i in xs]
plt.xticks(xs, x_labels, rotation='vertical')
plt.xlabel("Valeur binaire")
plt.ylabel("Valeur décimale du nombre flottant")
plt.title('Densité des valeurs flottantes sur 7 bits(e=3, f=3)',pad=30)
# Add colorbar
cbar = fig.colorbar(im, label="Densité des nombres")
#ax.set_yscale('log')
plt.show()
On voit que la densité est plus importante pour les nombres autour de et plus faible pour les très petits et très grands nombres.
Représentation d’un nombre dénormalisée
La norme IEEE-754 prévoit d’attribuer des valeurs spéciales aux nombres ayant un exposant nul ou maximum.
Notamment pour les nombres avec un exposant nul et une mantisse non nulle, on utilise une représentation d’un nombre dénormalisé.
La valeur du nombre représenté vaut : valeur = signe × (mantisse) × 2^− décalage^
# On limite les points pour y voir quelquechose
NBITS = 7
EXPOSANT=3
MANTISSE=3
x_list= [i for i in range(2**NBITS)]
N = len(x_list)
x = np.array(x_list)
x_bin = np.array([format(i, f'0{NBITS}b') for i in x])
y = np.array([bin2float(i, e=EXPOSANT, f=MANTISSE, ieee=True) for i in x_bin])
np.nan_to_num(y, copy=False, nan=2**(NBITS-2.5), posinf=2**(NBITS-2), neginf=-2**(NBITS-2))
# Calculate the point density
xy = np.vstack([x,y])
z = gaussian_kde(xy)(xy)
# Sort the points by density, so that the densest points are plotted last
idx = z.argsort()
x, y, z = x[idx], y[idx], z[idx]
fig, ax = plt.subplots()
im = ax.scatter(x, y, marker='+', c=z, s=100, alpha=0.5)
xs = [i for i in x_list if 10*i % 2**(NBITS-2) == 0] + [2**(NBITS)-1]
x_labels = [format(i, f'0{NBITS}b') for i in xs]
plt.xticks(xs, x_labels, rotation='vertical')
plt.xlabel("Valeur binaire")
plt.ylabel("Valeur décimale du nombre flottant")
plt.title('Densité des valeurs flottantes sur 7 bits(e=3, f=3)',pad=15)
plt.suptitle('La norme IEEE754 est appliquée avec les valeurs normalisés les nan et les infinis')
# Add colorbar
cbar = fig.colorbar(im, label="Densité des nombres")
#ax.set_yscale('log')
plt.show()
On peut voir que l’on a perdu en étendue, mais cela d’avoir des points trop éloignés pour les grandes valeurs.
D’autre part, grâce à la normalisation la densité semble plus uniforme.