Patrice Ferlet
Patrice Ferlet
Créateur de ce blog.
Publié le févr. 18, 2009 Temps de lecture: 3 min

Me suivre sur Mastodon

PHP les grands nombres et la notation scientifique

PHP gère les grands nombres sans trop de souci, malheureusement il arrive parfois que les bases de données retournent un grand nombre sous forme scientifique. Là où cela se complique c’est quand le nombre que nous voulons reformater est à virgule flottante. Laissez moi vous montrer.

Imaginons un nombre retourné par une base sous forme scientifique, par exemple //1.1e+6// qui correspond en fait à //1 100 000//. Ici la manière la plus simple pour représenter le nombre sous une jolie forme est: echo number_format(1.1e+6); 1 100 000

Pas trop d’effort, PHP a remis les choses en place. Voyons maintenant ce que donne //1.1234567e+6// qui est en fait la forme scientifique de //1 123 456.7//. **Notez bien la virgule !** et faisons de même: echo number_format(1.1234567e+6); 1,1231,457

Problème, on a perdu notre virgule et on a un arrondi… qu’à cela ne tienne, nous allons reformater le nombre en flottant: echo number_format(1.1234567e+6,2); 1,123,456.70

Jusque là, on a trouvé une solution… Pour la plupart des cas cela va vous permettre de corriger le problème, seulement j’ai eut un cas où je devais reformater des prix élevés formatés en notation scientifique mais il fallait que je ne fasse apparaitre la virgule que dans le cas où il y a une partie décimale…

Voilà donc ma méthode, certainement pas optimale, mais qui fonctionne: -je récupère la notation -je vérifie que la valeur entière est différente de la valeur sous forme décimale -si oui, je met “2” en paramètre à number_format pour demander deux chiffres après la virgule -si non je met “null” en paramètre à number_format pour supprimer la virgule Voici: function format_number($num, $floatsep=",", $thouthandsep=" "){ $float = null; if((int)$num != (float)$num ) $float = 2; return number_format($num,$float,$floatsep,$thouthandsep); }

Remarquez “$floatsep” et “$thouthandsep” qui sont respectivement les séparateur de virgule et de milier (différent pour les américains et les français) qui peuvent être utiles (voir plus bas). Testons notre fonction:

php > echo format_number(1.1234567e+6);
1 123 456,70
php > echo format_number(1.123456e+6);
1 123 456

Et voilà… **ATTENTION** n’envoyez **pas de chaine de caractère** mais bien des nombres **sans guillemets** à la fonction. J’entend par là que la notation scientifique n’est pas une chaine de caractères! Ne vous inquiétez pas vos base de données vous renvoient bien des variables de type __float__ ou __int__… Si vous englobez la notation scientifique dans une chaine de caractères, vous aurez à coup sûr un flottant car le test //(int)$num != (float)$num// sera **TOUJOURS VRAI** (les deux valeurs seront différentes… vous pouvez tester).

Bref, cette fonction me sert à formater des prix, mais vous pouvez vous en servir pour la suite. Par contre n’utilisez cette fonction qu’avant affichage car la valeur retournée est une chaine. La méthode pour pallier à cela:

#ici vous voyez le problème:
php > $a = format_number(1.1234567e+6);
php > $b = format_number(2.1234567e+6);
php > echo $a + $b;
3

#ici, on a beau faire ce qu'on veut... ça marche pas
php > $a = (float)format_number(1.1234567e+6);
php > $b = (float)format_number(2.1234567e+6);
php > echo $a + $b;
3

#la solution, mettre un séparateur de virgule "."
#et pas d'espace pour le spérateur de miliers:
php > $a = format_number(1.1234567e+6, '.', '');
php > $b = format_number(2.1234567e+6, '.', '');
php > echo $a + $b;
3246913.4
#pour le fun
php > format_number($a+$b)
3 246 913,40

En espérant que cela puisse vous servir.

comments powered by Disqus