import numpy as np
import struct
from .config import est_pedagogique
[docs]
def decimal_vers_binaire(x, bits=32):
"""Convertir un nombre decimal en representation binaire (chaine)."""
if bits == 32:
return f"{struct.unpack('!I', struct.pack('!f', x))[0]:032b}"
elif bits == 64:
return f"{struct.unpack('!Q', struct.pack('!d', x))[0]:064b}"
else:
raise ValueError("Seuls 32 et 64 bits sont supportes")
[docs]
def binaire_vers_decimal(chaine_binaire):
"""
Convertir une chaine binaire en nombre decimal.
Args:
chaine_binaire (str): Chaine de 32 ou 64 bits.
Returns:
float: Le nombre decimal correspondant.
"""
if len(chaine_binaire) == 32:
return struct.unpack('!f', struct.pack('!I', int(chaine_binaire, 2)))[0]
elif len(chaine_binaire) == 64:
return struct.unpack('!d', struct.pack('!Q', int(chaine_binaire, 2)))[0]
else:
raise ValueError("La chaine binaire doit etre de 32 ou 64 bits")
[docs]
def ieee754_encoder(x, precision="simple"):
"""Encoder un flottant en composants IEEE754."""
if precision == "simple":
b = decimal_vers_binaire(x, 32)
return {"signe": b[0], "exposant": b[1:9], "mantisse": b[9:]}
else:
b = decimal_vers_binaire(x, 64)
return {"signe": b[0], "exposant": b[1:12], "mantisse": b[12:]}
[docs]
def ieee754_decoder(bits_dict):
"""Decoder des composants IEEE754 en flottant."""
b = bits_dict["signe"] + bits_dict["exposant"] + bits_dict["mantisse"]
return binaire_vers_decimal(b)
[docs]
def representation_flottant(x, precision="simple"):
"""Representation prete pour examen."""
parties = ieee754_encoder(x, precision)
res = f"Valeur: {x}\n"
res += f"Signe: {parties['signe']}\n"
res += f"Exposant: {parties['exposant']}\n"
res += f"Mantisse: {parties['mantisse']}"
print(res)
return res
def est_normalise(x):
if x == 0: return False
parties = ieee754_encoder(x)
return parties["exposant"] != "00000000" and parties["exposant"] != "11111111"
def est_denormalise(x):
if x == 0: return False
parties = ieee754_encoder(x)
return parties["exposant"] == "00000000" and "1" in parties["mantisse"]
def demo_annulation():
print("--- Demo Annulation Catastrophique ---")
x = 1.23456789012345
y = 1.23456789012344
diff = x - y
print(f"x = {x:.15f}, y = {y:.15f}")
print(f"x - y = {diff:.15e}")
def demo_absorption():
print("--- Demo Absorption ---")
x = 1e16
y = 1.0
print(f"x = {x:.1e}, y = {y}")
print(f"x + y = {(x + y):.1e}")
def erreur_absolue(reel, approx, pedagogique=None):
err = np.abs(reel - approx)
if est_pedagogique(pedagogique):
print(f"[Pedagogique] Erreur Absolue: |{reel} - {approx}| = {err}")
return err
[docs]
def erreur_relative(reel, approx, pedagogique=None):
"""
Calcule l'erreur relative entre une valeur reelle et son approximation.
Args:
reel (float): Valeur exacte.
approx (float): Valeur approchee.
pedagogique (bool, optional): Affiche les etapes si True.
Returns:
float: L'erreur relative.
"""
if reel == 0: raise ValueError("Erreur relative non definie")
err = np.abs(reel - approx) / np.abs(reel)
if est_pedagogique(pedagogique):
print(f"[Pedagogique] Erreur Relative: |{reel} - {approx}| / |{reel}| = {err}")
return err
def arrondir_flottant(x, chiffres, pedagogique=None):
return np.round(x, chiffres)
def tronquer_flottant(x, chiffres, pedagogique=None):
facteur = 10.0 ** chiffres
return np.trunc(x * facteur) / facteur
def epsilon_machine(dtype=float):
return np.finfo(dtype).eps
def info_flottant():
print("Standard IEEE 754: Simple (32-bit), Double (64-bit).")