Hello,

J'ai du mal à bien comprendre comment est fait l'arrondi dans le cas d'une soustraction en mode arrondi au plus proche, puis à un nombre pair en cas d'égalité (le plus courant).

J'ai implémenté les multiplications et additions sans trop de soucis (ya juste beaucoup de cas particuliers..), mais dans le cas de soustraction, j'ai un problème avec l'arrondi.

Un exemple
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
a = 1 01111111 00001000011101010110000
b = 0 01111100 01100101111000110000100
 
résultat attendu pour a-b : 1 01111110 10110111011100011111111
Tout d'abord je vérifie les signes : ils sont différents, c'est bien une soustraction.

Je compare les exposants (puis les mantisses dans le cas où les exposants sont égaux) pour trouver le nombre avec la plus grande valeur absolue, et je calcule la différence pour les exposants.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
max = 1 01111111 00001000011101010110000
min = 0 01111100 01100101111000110000100
 
diff = 01111111 - 01111100 = 3
J'extrais les mantisses, rajoute le bit implicite, et décale la mantisse de "min" de "diff" bits vers la droite. Enfin j'inverse la mantisse de "min"
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
mant_max = 1000 0100 0011 1010 1011 0000
mant_min = 0001 0110 0101 1110 0011 0000    100
mant_inv = 1110 1001 1010 0001 1100 1111    011
Les bits sortant à droite sont conservés pour l'arrondi. (Le "sticky bit" passe à 1 ici).
Je calcule ensuite la mantisse résultante (mant_max - mant_min == mant_max + not(mant_min) + 1)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
mant_result = 0110 1101 1101 1100 1000 0000    011
Je décale ensuite le résultat à gauche jusqu’à ce que le 24eme bit soit à 1 (on décale de "x" bits), et je complète à droite avec les bits que j'avais conservé.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
mant_result = 1101 1011 1011 1001 0000 0000    11
L'exposant du résultat est donné par exposant_max - x, ici "x" vaut 1.
Pour la mantisse, les 2 bits de poids fort de la partie conservée sont les bits "guard" et "round", le "sticky" est un OR de tous les autres (une fois que le sticky passe à 1, il y reste).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
expo_result = 01111111 - 1 = 01111110
guard_bit = 1
round_bit = 1
sticky_bit = 1
Deux cas possible :
arrondi à la valeur inférieure -> on ne fait rien
arrondi à la valeur supérieure -> on ajoute 1 à la mantisse

On est dans le cas d'un arrondi à la valeur supérieure. Puis dernière étape : reconstruire le résultat.
Le signe du résultat est le signe de "max". Pour la mantisse on garde seulement les 23 bits de poids faible (on supprime le bit implicite).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
mant_result = 1101 1011 1011 1001 0000 0001
expo_result =  01111110
sign_result = 1
 
resultat = 1 01111110 10110111011100100000001
attendu  = 1 01111110 10110111011100011111111
Il y à une différence de 2 pour la mantisse, si j'avais enlevé 1 au lieu d'ajouter 1 lors de l'arrondi, j'aurais eu le bon résultat.

Pourquoi ?
Le signe du résultat doit être pris en compte lors de l'arrondi pour savoir si on ajoute ou enlève 1 ?

Les cas particuliers ne sont pas pris en compte ici : ajustement le l'exposant en cas de nombres dénormalisés, ajustement de l'exposant en cas d'overflow de la mantisse, mise à +/-infini en cas d'overflow de l'exposant, NaN, infinis...