Nombre dénormalisé
# Nombre dénormalisé

La notion de nombre dénormalisé intervient dans la représentation des nombres en informatique par la méthode de la virgule flottante, telle que normalisé par la norme IEEE 754. C'est une manière de représenter des nombres ayant une valeur très proche de zéro.

## Prérequis

La représentation en virgule flottante pour les ordinateurs est fondée sur deux notions : la notation scientifique et le système binaire (ou base 2).

Pour écrire les nombres en base 10, on peut utiliser la notation dite « scientifique », qui comprend deux parties :

* un nombre décimal n, positif ou négatif, dont la valeur absolue est comprise entre 1 inclus et 10 exclus ; 1 ≤ n < 10 ;
* une puissance entière de 10, a ;

sous la forme « n × $10^a$ ». Par exemple :

* 1 en écriture scientifique se note « 1 × $10^0$ » ;
* -85 en écriture scientifique se note « -8,5 × $10^1$ » ;
* 0,012 3 en écriture scientifique se note « 1,23 × $10^{−2}$ ».

Le terme « exposant » correspond à la puissance de 10, et le terme mantisse correspond à la partie décimale. Ainsi, dans « 1,23 × $10^{−2}$ »,

* la mantisse (ou significande) est « 1,23 » ;
* l'exposant est « -2 ».

Le système binaire, dit aussi « base 2 », est une manière de noter les nombres ne faisant intervenir que deux chiffres, 0 et 1. Il est bien adapté à l'électronique, puisque cela correspond à deux états bien distincts : on a aux bornes d'un composant une tension $V_0$ ou une tension $V_1$ (« le courant ne passe pas ou le courant passe »). Pour distinguer cette notation de la notation décimale, nous ajoutons ici un « b » à la fin du nombre. Voici quelques exemples de nombres :

* 0b = 0
* 1b = 1 ;
* 10b = 2 ;
* 11b = 3 ;
* 0,1b = 0,5 ;
* 0,01b = 0,25 ;
* 0,11b = 0,75 ;

Un nombre binaire à virgule de quatre chiffres $n_1n_0,n_{-1}n_{-2}b$ correspond au nombre décimal $n_1$ × $2^1$ + $n_0$ × $2^0$ + $n_{-1}$ × $2^{-1}$ + $n_{-2}$ × $2^{-2}.$

On peut ainsi avoir une notation scientifique binaire :

    $n_1n_0,n_{-1}n_{-2}b$ peut se noter $n_1,n_0n_{-1}n_{-2}b$ × $2^1.$

par exemple

* 11b = 1,1b × $2^1$
* 0,11b = 1,1b × $2^{-1}$

Dans le cas de la notation scientifique binaire, le nombre à virgule doit être compris entre 1b inclus et 10b exclus (c'est-à-dire 2 exclus), c'est-à-dire que sa partie entière est nécessairement 1b.

## Représentation d'un nombre normalisé

Selon ladite norme, la représentation d'un nombre réel peut se décomposer en trois parties :

* le signe, +1 ou -1, sous la forme de un bit ;
* l'exposant décalé, sous la forme de e bits représentant un nombre entier ;
* la mantisse, sous la forme de m bits représentant un nombre positif strictement inférieur à 1.

La valeur du nombre représenté vaut :

    valeur = signe × (1 + mantisse) × $2^{(exposant−décalage)}$

En effet, en notation scientifique en base binaire, la partie entière est nécessairement 1, il est donc inutile d'utiliser un bit pour la représenter, on se contente de représenter la partie fractionnaire.

## Représentation d'un nombre dénormalisé

Un nombre est dit dénormalisé lorsque

* exposant = 0, et
* mantisse ≠ 0.

Si l'on suivait la même représentation que pour les nombres à exposant non nul, on aurait

    valeur = signe × (1 + mantisse) × $2^{-décalage}$

mais la valeur retenue est

    valeur = signe × mantisse × $2^{-décalage+1}$

c'est-à-dire que pour un exposant codé sur 8 bits (représentation dite à simple précision), on a

    valeur = signe × mantisse × $2^{-126}$

et que pour un exposant codé sur 11 bits (représentation dite à double précision), on a

    valeur = signe × mantisse × $2^{-1022}$

## Raison de cette représentation

Avec les nombres dénormalisés, on abandonne la notation scientifique. Si la mantisse correspond à 0,1b (le « b » signifie que l'on est en mode binaire, en base deux), alors :

* avec la représentation normalisée, on aurait valeur = 1,1b × $2^{-décalage}$ ;
* avec la représentation dénormalisée, on a valeur = 0,1b × $2^{-décalage+1}$ = 1b × $2^{-décalage}$

on voit ainsi que le plus petit nombre représentable de manière normalisée est 1,000…00b × $2^{-décalage}$ (puisqu'une mantisse nulle et un exposant nul servent à représenter le zéro), alors qu'en représentation dénormalisée, c'est 0,000…01b × $2^{-décalage}.$ On peut donc représenter des nombres plus petits. Cela assure également une continuité avec les nombres normalisés, puisque :

* le plus petit nombre normalisé vaut 1,000…00b × $2^{-décalage+1}$
* le plus grand nombre dé normalisé vaut 0,111…11b × $2^{-décalage+1}$

soit un « saut » de 0,000…01b × $2^{-décalage+1}$

Nous avons donc, en simple précision :

| Type | Exposant | Mantisse | Valeur approchée | Écart / préc |
| - | - | - | - | - |
| Zéro | 0000 0000 | 000 0000 0000 0000 0000 0000 | 0,0 | |
| Plus petit nombre dénormalisé | 0000 0000 | 000 0000 0000 0000 0000 0001 | 1,4 × $10^{−45}$ | 1,4 × $10^{−45}$ |
| Nombre dénormalisé suivant | 0000 0000 | 000 0000 0000 0000 0000 0010 | 2,8 × $10^{−45}$ | 1,4 × $10^{−45}$ |
| Nombre dénormalisé suivant | 0000 0000 | 000 0000 0000 0000 0000 0011 | 4,2 × $10^{−45}$ | 1,4 × $10^{−45}$ |
| Plus grand nombre dénormalisé | 0000 0000 | 111 1111 1111 1111 1111 1111 | 1,175 494 21 × $10^{−38}$ | 1,4 × $10^{−45}$ |
| Plus petit nombre normalisé | 0000 0001 | 000 0000 0000 0000 0000 0000 | 1,175 494 35 × $10^{−38}$ | 1,4 × $10^{−45}$ |
| Nombre normalisé suivant | 0000 0001 | 000 0000 0000 0000 0000 0001 | 1,175 494 49 × $10^{−38}$ | 1,4 × $10^{−45}$ |

## Impact sur les performances

Certaines architectures réalisent des opérations sur les nombres dénormalisés au niveau matériel, cependant il est possible que ces opérations soient effectuées au niveau logiciel. Cela peut avoir pour conséquence de créer des ralentissements conséquents.

Il est possible de demander au processeur de traiter ces nombres au niveau matériel en les ramenant à 0 soit Flush-To-Zero (FTZ) et Denormals-Are-Zero (DAZ). Il faut pour cela activer les bons registres :

sur x86_64:

sur Aarch64:

