web-dev-qa-db-fra.com

Comment normaliser une mantisse

J'essaie de convertir un int en un flotteur personnalisé, dans lequel l'utilisateur spécifie la quantité de bits réservés pour l'exp et la mantisse, mais je ne comprends pas comment fonctionne la conversion. Ma fonction prend une valeur int et et int exp pour représenter le nombre (valeur * 2 ^ exp) c'est-à-dire valeur = 12, exp = 4, renvoie 192. mais je ne comprends pas le processus que je dois faire pour les changer. Je regarde cela depuis des jours et je joue avec les applications Web du convertisseur IEEE, mais je ne comprends tout simplement pas le processus de normalisation. Comme si je voyais que c'était "déplacer le point binaire et ajuster l'exposant" mais je n'ai aucune idée de ce que cela signifie, quelqu'un peut-il me donner un exemple à suivre? Je ne comprends pas non plus quel est le biais de l'exposant. La seule information que j'ai, c'est que vous ajoutez simplement un nombre à votre exposant mais je ne comprends pas pourquoi. J'ai cherché sur Google un exemple que je peux comprendre, mais cela n'a aucun sens pour moi

12
Tommy K

Un nombre à virgule flottante est normalisé lorsque nous forçons la partie entière de sa mantisse à être exactement 1 Et permettons à sa partie fraction d'être ce que nous aimons.

Par exemple, si nous prenions le nombre 13.25, Qui est 1101.01 En binaire, 1101 Serait la partie entière et 01 Serait la fraction partie.

Je pourrais représenter 13.25 Comme 1101.01*(2^0), mais ce n'est pas normalisé car la partie entière n'est pas 1. Cependant, nous sommes autorisés à décaler la mantisse vers la droite d'un chiffre si nous augmentons l'exposant de 1:

  1101.01*(2^0)
= 110.101*(2^1)
= 11.0101*(2^2)
= 1.10101*(2^3)

Cette représentation 1.10101*(2^3) est la forme normalisée de 13.25.


Cela dit, nous savons que les nombres à virgule flottante normalisés viendront toujours sous la forme 1.fffffff * (2^exp)

Pour des raisons d'efficacité, nous ne prenons pas la peine de stocker la partie entière 1 Dans la représentation binaire elle-même, nous prétendons simplement qu'elle est là. Donc, si nous devions donner à votre flotteur sur mesure 5 bits pour la mantisse, nous saurions les bits 10100représenterait en fait 1.10100.

Voici un exemple avec la mantisse 23 bits standard:

enter image description here


En ce qui concerne le biais d'exposant, jetons un coup d'œil au format standard 32 bits float, qui est divisé en 3 parties: 1 bit de signe, 8 bits d'exposant et 23 bits de mantisse:

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm

Les exposants 00000000 Et 11111111 Ont des fonctions spéciales (comme représenter Inf et NaN), donc avec 8 bits d'exposant, nous pourrions représenter 254 exposants différents, disons 2^1 À 2^254, Par exemple. Mais que se passe-t-il si nous voulons représenter 2^-3? Comment obtient-on des exposants négatifs?

Le format corrige ce problème en soustrayant automatiquement 127 de l'exposant. Par conséquent:

  • 0000 0001 Serait 1 -127 = -126
  • 0010 1101 Serait 45 -127 = -82
  • 0111 1111 Serait 127-127 = 0
  • 1001 0010 Serait 136-127 = 9

Cela modifie la plage d'exposants de 2^1 ... 2^254 À 2^-126 ... 2^+127 Afin que nous puissions représenter des exposants négatifs.

22
eigenchris

Le "processus de normalisation" convertit les entrées en une plage sélectionnée.

binary32 s'attend à ce que la signification (pas la mantisse) soit dans la plage 1.0 <= s < 2.0 à moins que le nombre ait un exposant minimum.

Exemple:
value = 12, exp = 4 Est identique à
value = 12/(2*2*2), exp = 4 + 3
value = 1.5, exp = 7

Puisque la signification a toujours un chiffre de tête de 1 (À moins que le nombre ait un exposant minimum), il n'est pas nécessaire de le stocker. Et plutôt que de stocker l'exposant sous 7, Un biais de 127 y est ajouté.

valeur = 1,5 décimal -> 1,1000 ... 000 binaire -> 0,1000 ... 000 binaire stocké (23 bits au total)
exp = 7 -> biais exp 7 + 127 -> 134 décimal -> 10000110 binaire

Le motif binaire stocké est la concaténation du "signe", "significande avec un bit de tête implicite" et un "exposant de biais"

0 10000110 1000...000 (1 + 8 + 23 = 32 bits)

Lorsque l'exposant biaisé est 0 - la valeur minimale, le bit implicite est 0 Et donc de petits nombres comme 0.0 Peuvent être stockés.

Lorsque l'exposant biaisé est 255 - la valeur maximale, les données stockées ne représentent plus des nombres finis mais "infini" et "Pas un nombre".

Consultez le lien référencé pour plus de détails.

4
chux

Tommy - chux et eigenchris, ainsi que les autres ont fourni d'excellentes réponses, mais si je regarde correctement vos commentaires, vous semblez toujours avoir du mal avec les écrous de "comment pourrais-je prendre cette information et ensuite utiliser cela en créant une représentation flottante personnalisée où l'utilisateur spécifie la quantité de bits pour l'exposant? " Ne vous sentez pas mal, c'est une boue claire comme la première douzaine de fois que vous traversez. Je pense que je peux essayer de le clarifier.

Vous connaissez la représentation IEEE754-Single-Precision-Floating-Point de:

IEEE-754 Single Precision Floating Point Representation of (13.25)

  0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
 |s|      exp      |                  mantissa                   |

Que le 1-bit sign-bit, 8-bit biased exponent (en notation excédentaire-127 sur 8 bits), et le 23-bit mantissa.

Lorsque vous autorisez l'utilisateur à choisir le nombre de bits dans l'exposant, vous devrez retravailler la notation d'exposant pour travailler avec la nouvelle limite choisie par l'utilisateur.

Qu'est-ce que cela changera?

  • Cela changera-t-il le sign-bit manipulation - Non.

  • Cela changera-t-il la gestion de mantissa - Non (vous convertirez toujours la mantisse/significande au format "bit caché").

Donc, la seule chose sur laquelle vous devez vous concentrer est exponent handling.

Comment aborderiez-vous cela? Rappelons que l'exposant 8 bits actuel est dans ce qu'on appelle notation excès-127 (où 127 représente la plus grande valeur pour 7 bits permettant à tout biais d'être contenu et exprimé dans le courant 8-bit limite. Si votre utilisateur choisit 6 bits comme taille d'exposant, alors quoi? Vous devrez fournir une méthode similaire pour vous assurer que vous avez un nombre fixe pour représenter votre nouvelle notation excess - ## qui fonctionnera dans la limite de l'utilisateur.

Prenez un 6-bit limite utilisateur, un choix pour la valeur d'exposant non biaisé pourrait être tenté comme 31 (les plus grandes valeurs pouvant être représentées dans 5-bits). Pour cela, vous pouvez appliquer la même logique (en prenant l'exemple 13.25 ci-dessus). Votre représentation binaire pour le nombre est 1101.01 vers lequel vous déplacez la décimale 3 positions to the left obtenir 1.10101 ce qui vous donne un biais d'exposant de 3.

Dans votre 6-bit exponent cas où vous ajouteriez 3 + 31 pour obtenir votre excess-31 notation pour l'exposant: 100010, puis mettez la mantisse au format "bit caché" (c'est-à-dire supprimez le _ 1 de 1.10101 résultant en votre nouvelle représentation Tommy Precision personnalisée:

IEEE-754 Tommy Precision Floating Point Representation of (13.25)

  0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
 |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
 |s|    exp    |                    mantissa                     |

Avec 1-bit sign-bit, 6-bit biased exponent (en notation excès-31 sur 6 bits), et le reste 25-bit mantissa.

Les mêmes règles s'appliqueraient à l'inversion du processus pour récupérer votre nombre à virgule flottante à partir de la notation ci-dessus. (en utilisant simplement 31 au lieu de 127 pour supprimer le biais de l'exposant)

J'espère que cela aide d'une certaine manière. Je ne vois pas grand-chose d'autre que vous puissiez faire si vous voulez vraiment autoriser une taille d'exposant sélectionnée par l'utilisateur. Rappelez-vous, la norme IEEE-754 n'était pas quelque chose qui a été deviné et beaucoup de bons raisonnements et compromis ont été faits pour arriver à la disposition 1-8-23 signe-exposant-mantisse. Cependant, je pense que votre exercice fait un excellent travail en vous obligeant à bien comprendre la norme.

Maintenant totalement perdu et non traité dans cette discussion est quels effets cela aurait sur la gamme de nombres qui pourraient être représentés dans ce Custom Precision Floating Point Representation. Je ne l'ai pas examiné, mais la principale limitation semble être une réduction du MAX/MIN qui pourrait être représenté.

3
David C. Rankin

Pour répondre à un commentaire publié sur "comment faire cela dans le code": (en supposant que c'est un flotteur IEEE)

A) Extraire un "exposant" et une "mantisse" non signés du flotteur IEEE.

je) exp = 0x7F800000 & yourFloatVar;

// cela prend les bits b1 à b8 du flotteur. (b0 est le bit signé, b9 et on est la mantisse)

ii) exp = exp >> 23; // déplacer vers la droite pour que cet exposant soit orienté vers la droite

iii) exp += 127; // ajoute le biais (127 est pour 32 bits uniquement)

iv) mantissa = 0x007FFFFF & yourFloatVar; // prend les 23 derniers bits de float

B) Normalisation

je)

while(true)
{
    if( ((mantissa & 0xC0000000) != 0x80000000)
         &&((mantissa & 0xC0000000) != 0x40000000) )
    {
        mantissa = mantissa << 1;
        exponent--;
    }
    else //AKA the float has been normalized
    {
        break;
    }
}

si les 2 bits de tête ne sont pas "01" ou "10" (c'est une propriété du complément à 2 - la condition pour normaliser), alors déplacez la mantisse et décrémentez l'exposant.

Je veux noter que ce n'est pas du tout l'algorithme le plus efficace pour le faire; Je voulais juste clarifier les étapes. J'espère que je n'ai rien manqué!

0
J. Doe

Pour normaliser une mantisse, vous placez le point décimal à gauche du chiffre non nul le plus à gauche

par exemple

représenter 10,11 base 2 sous forme de normalisation

= 0,1011 base 2 * 2 à la deuxième puissance

la base de deux est parce que vous travaillez avec des nombres binaires et la puissance de + ve 2 est parce que vous avez déplacé la virgule décimale vers la gauche deux fois. N'oubliez pas que seuls 4 bits sont utilisés pour la mantizza

de sorte que le mantizza serait 1011

0
Questionare232