Outils d'utilisateurs

Outils du Site


virgule_fixe

Ceci est une ancienne révision du document !


Chapitre précédent Sommaire principal Chapitre suivant

Les nombres à virgule fixe

Limitation des nombres réels

Les nombres réels sont intéressants, puisqu'ils permettent de représenter des nombres plus grands que les nombres entiers. Si par exemple, vous essayez d’exécuter le code suivant, vous obtiendrez une erreur :

main.cpp
#include <iostream>
 
int main() {
    std::cout << 9223372036854775808 << std::endl;
}

affiche (seules les premières erreurs sont copiées ici) :

main.cpp:4:26: warning: integer constant is so large that it is unsigned
     std::cout << "  " << 9223372036854775808 << std::endl;
                          ^
main.cpp: In function 'int main()':
main.cpp:4:15: error: ambiguous overload for 'operator<<' (operand types are 
'std::basic_ostream<char>' and '__int128')
     std::cout << 9223372036854775808 << std::endl;
               ^
...

La première erreur “integer constant is so large that it is unsigned” indique que le nombre entré est tellement grand qu'il n'existe pas de type signé (signed, qui peut représenter de nombres positifs et négatifs) qui peut représenter ce nombre. Le compilateur est donc obligé d'utiliser un type non signé (unsigned, qui ne peut représenter que des nombres positifs).

La seconde erreur “ambiguous overload” indique que le compilateur ne sait pas comment afficher ce nombre (plus précisément, il ne sait pas quel opérateur « utiliser avec std::cout pour afficher ce nombre).

Note : ce nombre n'a pas été choisit au hasard. Il s'agit du plus grand nombre représentable avec les types de base du C++, plus un. Vous verrez par la suite comment obtenir des informations sur les types, comme par exemple la valeur maximal possible.

Si on modifie un tout petit peu ce code (en ajoutant une décimale), pour utiliser des nombres réels, le compilateur ne produit plus d'erreur :

main.cpp
#include <iostream>
 
int main() {
    std::cout << 9223372036854775808.0 << std::endl;
}

affiche :

9.22337e+18

Comme on peut s'y attendre, le programme affiche le nombre en utilisant la notation scientifique.

On retrouve ici un autre exemple du typage fort du C++. Le compilateur détecte bien que les nombres entiers ne conviennent pas pour représenter ce nombre. Mais comme vous avez choisi d'utiliser un entier, le compilateur ne fait pas la correction pour vous.

Une littérale est représentée par une valeur et un type. Le compilateur prend en compte les deux, pas uniquement la valeur.

Pour autant, les nombres réels ne sont pas parfaits non plus (sinon, on ne s’embêterait pas a faire la distinction entre entiers et réels). Prenons un autre code d'exemple :

main.cpp
#include <iostream>
 
int main() {
    std::cout << "  " << (9223372036854775807 - 9223372036854775806) << std::endl;
    std::cout << "  " << (9223372036854775807.0 - 9223372036854775806.0) << std::endl;
}

affiche :

1
0

On a donc deux nombres, représentées dans le premier cas par des entiers et dans le second par des réels (notez la décimale). Ces deux nombres sont grands, mais peuvent être représentée sans problème par des entiers en C++ (plus précisément par le type long long int, que vous verrez ensuite). La différence entre ces deux nombres vaut un.

Dans tous les cas, les nombres en C++ sont représentés par un nombre fini d'octets dans la mémoire des ordinateurs. Il n'est donc pas possible de représenter tous les nombres possibles (ce qui n'aurait de toute façon aucun sens, puisque qu'il existe une infinité de nombres réels). Les nombres réels peuvent représenter des nombres plus grands que les nombres entiers parce qu'ils ne peuvent pas représenter les grands nombres avec la même précision que les nombres entiers.

Dans le code d'exemple précédent, les nombres entiers ne sont pas arrondis et le calcul est juste. Au contraire, les nombres réels sont arrondis et sont représentées par la même valeur en mémoire. Le calcul se fait donc sur la même valeur et le résultat est nul.

<note>Encore une fois, il est important d'insister la dessus : les types ont une grande importance en C++. Le choix du type peut modifier complètement le résultat d'un calcul. Faites bien attention a cela, c'est une erreur qui revient souvent.</code>

Principe des nombres à virgule fixe

Imaginons que vous souhaitez travailler sur des nombres décimaux, mais en conservant la précision des nombres entiers (vous ne voulez pas que les valeurs soient arrondies). Par exemple, dans une application bancaire, qui manipule des centimes (deux chiffres après la virgule).

Avec les nombres à virgule flottante, un problème de représentation de certain nombre avec virgule, qui ne sont pas représentable selon le type de réel. donner un exemple Cette différence entre la valeur réelle et sa représentation dans un ordinateur peut être problématique.

De plus, les calculs sur les nombres réels sont parfois plus longs que sur les nombres entiers.

La solution : mutliplier les nombres (pour les calculs) par une constante multiple de 10 et afficher le nombre réel. Par exemple, 123.45 sera écrit 12345 avec multiplicateur de 100

Erreur d'arrondi lors des conversions, mais les calculs sont exacts

Astuce : généralisable (mais s'appelle pas nombre à virgule fixe). Si par exemple compter de 1 à 10 avec pas de 1/3, compter de 1 à 30 et diviser pas 3

Chapitre précédent Sommaire principal Chapitre suivant
virgule_fixe.1435673358.txt.gz · Dernière modification: 2015/06/30 16:09 par gbdivers