Convertir une chaîne javascript en Number

En javascript, lorsque l’on veut transformer une chaîne en Number, il est nécessaire de prendre un certain nombre de précautions.
Rappelons d’abord, que javascript ne comporte qu’un seul type de nombre : Number et pas de différentiation entre nombre flottants ou entiers, ni même de gestion de la précision.
Les nombres javascript sont implantés sous forme de nombres flottants à 64 bits, conformément la norme IEEE-754 (ce qu’on appelle généralement un « Double » pour IEEE-754).
Il existe au moins 3 façons de convertir une chaîne en flottant en javascript, via les fonctions parseInt et parseFloat, par le constructeur Number, et en préfixant une chaîne par l’opération + avec un nombre (par exemple +"125" donne bien 125).

La fonction parseInt

Concentrons nous sur la notion d’entier et donc sur la fonction parseInt.
La fonction parseInt peut prendre un ou deux arguments :
• le premier argument est la chaîne à convertir.
• Le second argument est la base à utiliser pour la conversion.
Il est fondamental de toujours préciser le deuxième argument. En effet, javascript utilise un certain nombre de conventions concernant la représentation des nombres sous forme de chaînes.
Ainsi, si la chaîne commence par 0, javascript considère automatiquement qu’il s’agit d’un nombre en octal.
Si la chaîne commence par 0x, javascript considère automatiquement qu’il s’agit d’un nombre en hexadécimal.
Ainsi :

parseInt("0125") est interprété comme de l’octal et donne 85 en base 10
parseInt("125") est interprété comme du décimal et donne 125.

Pour plus de sécurité, il est préférable de préciser que l’on veut parser la chaîne en base 10 :

parseInt("0125",10) donne bien 125.

Une autre alternative serait de prétraiter la chaîne en supprimant tous les 0 non significatifs (les zéros à gauche).
Une particularité, dangereuse, de parseInt est d’arrêter son analyse au premier caractère non conforme à la base utilisée, mais de ne pas déclencher d’erreur.
Ainsi,

parseInt("125kjekje",10) donne 125,
parseInt("kjekje",10) donne NaN,
parseInt("0129F") donne 10 (interprétation en base octale, on s'arrête avant le 9 qui ne fait pas partie des caractères utilisables en octal)
parseInt("0129F",10) donne 129 (parseInt s'arrête avant le F qui ne fait pas partie des caractères utilisables en décimal)
parseInt("0129F",16) donne 4767 (interprétation en base hexadécimale)
parseInt("0x129F") donne 4767 (interprétation en base hexadécimale)

Si l’on veut garantir un minimum de sécurité, il est donc nécessaire de vérifier que la chaîne à transformer ne comporte que des caractères valides.
Par exemple, si on utilise la base 10 et que l’on veut autoriser des entiers signés, on peut utiliser une expression régulière telle que :

var reg=/^(+|-)?d+$/
var isNumeric=reg.test(anObject);
if(isNumeric) {
aNumber=parseInt(anObject,10);
}

Bien entendu, il faut modifier l’expression régulière en fonction de la base que l’on souhaite utiliser.

Le constructeur Number

Une autre solution, est l’utilisation du constructeur Number, directement ou via new Number

Number("125") donne 125
Number ("0125") donne là aussi 125 (dans ce cas, pas d’interprétation en octal !)
Number (0125) donne 85 (le littéral 0125 est interprété en octal)

ces deux derniers exemples prouvent qu’il est préférable de tester que le type d’argument utilisé est bien une String, surtout lorsqu’une partie de la génération du code javascript est réalisée côté serveur (il suffit de générer le littéral sans les quotes pour qu’il soit interprété comme de l’octal).

Number ("0x125") donne 293 (interprétation en hexadécimal)
Number ("125kjekje") donne NaN
Number("kjekje") donne NaN

NaN est un nombre spécial qui signifie « Not a Number », c’est la valeur rendue pour signifier le résultat indéfini ou erroné d’opérations arithmétiques ou de conversions.
Attention aux caractéristiques de NaN :
NaN n’est égal à rien, même pas à lui-même. Ainsi NaN==NaN et NaN===NaN rendent false.
Toute opération avec NaN en entrée rendra NaN.
typeof(NaN) rend number.
isNaN("125kjekje") rend true
On peut donc tester si l’opération de conversion a réussi de la façon suivante

var aNumber=new Number(aString) ;
var isNumeric=! isNaN(aNumber)

Le problème de la précision

Noter néanmoins que ces tests ne garantissent rien en ce qui concerne le dépassement de la précision autorisée par les doubles 64 bits définis par IEEE 754.
Par exemple, l’expression régulière qu’on a utilisé avec parseInt teste bien qu’une chaîne ne comporte que des chiffres (éventuellement préfixé par le signe + ou le signe -), mais il n’y a pas de garantie que ce nombre est représentable en 64 bits.
Cette représentation 64 bits correspond à :
• la mantisse pour les bits de 0 à 51,
• l’exposant pour les bits 52 à 62,
• le signe pour le bit de poids fort (bit 63)
mais il ne faut pas pour autant en déduire que pour un entier, la mantisse est la représentation binaire de ce nombre entier et en déduire qu’on peut représenter directement tout nombre entier inférieur à 2^52-1.

En effet, la mantisse représente les fractions de 2 (le 1 initial est implicite).
Pour ceux que les arcanes de la représentation IEEE 754 intéressent, ce site explique pas mal de choses. Et les convertisseurs (par exemple http://babbage.cs.qc.edu/IEEE-754/Decimal.html comportent le code javascript qui va bien pour faire ce genre de conversion.
Quand à la page http://www.binaryconvert.com/convert_double.html, elle permet de se faire une idée visuelle du fonctionnement de cette représentation.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.