Logo JavaScript

Les nombres en Javascript

Flattr this!

Dans la suite logique de mon billet sur la notion d'objets en JavaScript, voici un point sur les nombres.

Types

C'est simple et pourtant particulièrement méconnu, il n'y a qu'un type de nombres en JavaScript : Number. Quand vous pensez manipuler un entier, vous vous trompez. Pour plus de praticité, tout est flottant. Certes JS n'affichera pas le point séparateur et des décimales inutiles dans le cas d'entier mais c'est bien un flottant. Et comme tout est objet en JavaScript, l'objet derrière tout ça s'appelle Number.

Déclaration

Comme pour beaucoup de choses en JS, il y a plusieurs façons de faire :

var monNumber = 3;
var unAutreNumber = new Number(4.2);
var encoreUnAutreNumber = Number(5.8967);

Prototype

L'objet Number ne comprend que peu de méthodes :

toString(arg1)

Retourne une chaîne de caractères contenant la valeur de la variable. arg1 permet de définir dans quelle base sera transformé le nombre. toString(10) renvoie toujours le même résultat que toString().

var monNumber = 3;
var monNumberEnString = monNumber.toString();
// monNumberEnString = "3"
var autreNumber = 3;
var monNumberEnStringBase2 = autreNumber.toString(2);
// monNumberEnStringBase2 = "11"
Number(42).toString(8) // "52"
Number(42).toString(16) // "2a"

valueOf()

Retourne un Number contenant la valeur de la variable.

var monNumber = 3.1415;
var monNumberValue = monNumber.valueOf();
// monNumberValue = 3.1415

toPrecision(arg1)

Retourne une chaîne de caractères correspondant à la valeur de la variable à la précision passée en paramètre arg1. Si vous ne passez pas d'argument, toPrecision() fera exactement le même boulot que toString(10).

var monNumber = 42.136;
var monNumberPrecision = monNumber.toPrecision();
// monNumberPrecision = "42.136"
var monNumberPrecision4 = monNumber.toPrecision(4);
// monNumberPrecision4 = "42.14"
var monNumberPrecision5 = monNumber.toPrecision(6);
// monNumberPrecision5 = "42.1360"
var monNumberPrecision2 = monNumber.toPrecision(2);
// monNumberPrecision2 = "42"

Attention, comme vous aurez pu le remarquer, toPrecision() arrondit vos nombres.

toExponential(arg1)

Retourne une chaîne de caractères correspondant à la notation scientifique du nombre. Cette fonction est un faux ami pour les francophones. Le terme "exponential notation" ne signifie en rien notation exponentielle en français, mais bien notation scientifique. Pour rappel, voici un cours de rattrapage sur cette notation. Cette fonction prend un seul paramètre, celui-ci indique combien de décimales seront conservées dans l'écriture finale. Cet argument doit être écrit comme une valeur entière comprise entre 0 et 20. Exemple :

var nombre = new Number(42.356);
var nombreNotationScientifique = nombre.toExponential();
alert(nombreNotationScientifique); // affichera "4e+1"
alert(typeof nombreNotationScientifique); // affichera "string"

var nombreNotationScientifique0 = nombre.toExponential(0);
alert(nombreNotationScientifique0); // affichera "4e+1"

var nombreNotationScientifique5 = nombre.toExponential(5);
alert(nombreNotationScientifique5); // affichera "4.23560e+1"

var nombreNotationScientifique10 = nombre.toExponential(10);
alert(nombreNotationScientifique10); // affichera "4.2356000000e+1"

var nombreNotationScientifique20 = nombre.toExponential(20);
alert(nombreNotationScientifique20); // affichera "4.23560000000000016485e+1"

Vous remarquerez d'ailleurs qu'arrivé à un certain nombre de décimales, on perd en précision. Faites donc très attention quand vous manipulez les nombres.

toFixed(arg1)

Retourne une chaîne de caractères pour laquelle vous avez spécifié le nombre de décimales à utiliser. Attention, le nombre est arrondi et non pas tronqué. Comme pour toExponential(), un seul paramètre en écriture entière compris entre 0 et 20.

var nombre = new Number(42.356);
var nombreTronque = nombre.toFixed();
alert(nombreTronque); // affichera "42"
alert(typeof nombreTronque); // affichera "string"
var nombreTronque0 = nombre.toFixed(0);
alert(nombreTronque0); // affichera "42"
var nombreTronque2 = nombre.toFixed(2);
alert(nombreTronque2); // affichera "42.36"
var nombreTronque5 = nombre.toFixed(5);
alert(nombreTronque5); // affichera "42.35600"
var nombreTronque10 = nombre.toFixed(10);
alert(nombreTronque10); // affichera "42.3560000000"

toLocaleString()

Cette fonction retourne une chaîne de caractères lisible par l'Homme selon la locale de l'interpréteur, donc souvent celle du navigateur.

var monNumber = 42.136;
var monNumberString = monNumber.toLocaleString();
alert(monNumberString) = "42.136" // en français
alert(monNumberString) = "42,136" // en anglais

toSource()

Je ne présenterai pas cette fonction qui n'est pas un standard et ne fais donc, pour moi, pas partie du langage.

Calcul

Les opérateurs de calcul sont :

  • +, addition
  • -, soustraction
  • *, multiplication
  • /, division
  • %, modulo
  • ++, incrémentation
  • --, décrémentation

Chacun retourne un Number. D'ailleurs, hormis pour ++ et --, vous pouvez raccourcir vos écritures par : +=, -=, *=, /=, %=. Oui, modulo aussi.

Attention cependant aux opérateurs + et - que je vous conseille de surveiller.

Pourquoi ?

Parce que vous pourriez croiser un jour ce code :

var alpha = "33";
var oups = 2 + +alpha;

Eh eh, et là, vous comprenez quoi vous ? Bon en fait, c'est un peu piégeant et rare de trouver ce code mais avouez que ça vous démange. A l'occasion j'écrirais un billet sur les chaînes de caractères, en attendant, ici oups vaut 35. +alpha est une façon de demander à l'interpréteur JS de convertir provisoirement alpha en Number. Qui au passage est aussi une mauvaise pratique.

Encore pire

Je n'ai pas réussi à le reproduire sur nos navigateurs modernes (comprendre IE 9, FF 7 et Chrome 15) mais il y a encore peu, ceci était valide :

2+++3 // 5

Histoire de rigoler encore un coup

Et parce que JS aime jouer avec vos nerfs, + est aussi un opérateur de concaténation pour les chaînes. Méfiez vous en donc réellement.

Une petite dernière pour la route

Un bug est très régulièrement signalé, pour vous, combien vaut :

0.1 + 0.2

0.3 ? Faux ! Pour JavaScript, cela vaut 0.30000000000000004. C'est le seul cas que je connaisse dans cette situation et ce n'est même pas vrai avec -.

Je n'en ai plus sous la main, mais faites vraiment attention, l'opérateur + est vraiment dangereux. Qui aurait cru qu'il était si dur de faire une addition ?!

Propriétés constantes

JavaScript fournit des constantes  intéressantes liées à Number mais souvent méconnues.

Number.POSITIVE_INFINITY et Number.NEGATIVE_INFINITY valent respectivement Infinity et -Infinity. Ce sont également des nombres.

MAX_VALUE représente le nombre positif le plus grand positif possible pendant que -MAX_VALUE, la même chose mais en négatif.

MIN_VALUE représente le plus petit nombre positif possible pendant que -MIN_VALUE, la même chose mais en négatif.

Number.NaN est un entier qui n'en est pas un. C'est une valeur spéciale dont JS se sert pour identifier tout ce qui n'est pas entier. Méfiez-vous également comme de la peste. Pour tester si une variable vaut NaN, utiliser toujours la fonction isNaN(), pour la bonne raison que :

NaN === NaN // false
NaN !== NaN // true

Uh ?! Et oui, ça c'est un des nombreux pièges de JS où je ne compte plus le nombre de développeurs que j'ai vu courir dedans tête baissée. Donc je disais :

isNaN(NaN) // true
isNaN(2) // false
isNaN("toto") // true
isNaN("58") // false

J'en vois déjà se taper la tête sur les murs en se rappelant tous les codes qu'ils ont écrit et sur lesquels ils se sont arrachés les cheveux pour comprendre pourquoi ça plantait.

Opérations bit à bit

Rien de faramineux pour le coup, la liste des opérateurs est complète :

  • & correspond au ET logique : 1 & 1 === 1, 0 & 1 === 0, 2 & 3 === 2
  • | correspond au OU logique : 1 | 1 === 1, 0 | 1 === 1, 2 | 3 === 3
  • ^ correspond au OU exclusif logique : 1 ^ 1 === 0, 0 ^ 1 === 1, 2 ^ 3 === 1
  • ~ correspond au NON logique : ~1 === 0, ~0 === 1, ~2 === -3
  • << déplace les bits sur la gauche : 1<<2 === 4, 2<<1 === 4
  • >> déplace les bits sur la droite : 1>>2 === 0, 10>>1 === 5, -8>>2 === -2
  • >>> déplace les bits sur la droite mais écrase au passage le bit de contrôle, donnant un résultat toujours positif, du coup : 1>>2 === 0, 10>>1 === 5,-8>>>2 === 1073741822

Conclusion

Bon bah je crois qu'on a fait le tour hein. Rien de sorcier, quelques pièges que je me permets de vous rappeler encore :

  • +
  • -
  • ++ (histoire de ne pas s'embrouiller avec 2 + +"6")
  • -- (même chose 9 - -"7")
  • NaN
  • toFixed()
  • Pas d'entier, pas de double, que des floats

Flattr this!

A propos de Mathieu

Ingénieur développeur web dans la vente par correspondance B2B, adepte de nouvelles technologies et d'innovation. Vous pouvez aussi me retrouver sur Twitter @mathrobin
Cette entrée a été publiée dans JavaScript, avec comme mot(s)-clef(s) , , , . Vous pouvez la mettre en favoris avec ce permalien.
  • http://www.worldofmashup.fr/ m0hda

    Encore une fois, j’apprend quelques trucs dont j’avais pas connaissance (les petits pièges etc…).
    Je reste encore ton padawan sur ce domaine ^^

    • http://www.mathieurobin.com/ Mathieu

      Toujours un plaisir de te cultiver, tu m’aides bien en PHP 😉

  • http://www.pure-tentation.fr/ Syndrael

    Toujours utile une piqure de rappel.. Ce matin encore je cherchais la liste des fonctions sur les Array…toujours aussi maigre la liste native..
    S.

    • http://www.mathieurobin.com/ Mathieu

      22 méthodes natives pour les Array() quand même, en admettant, argh, que length est une méthode le temps de compter et sans compter le constructor. Par curiosité, qu’est-ce qui te manque ? C’est vrai que ce n’est pas aussi riche que dans les autres langages, mais l’essentiel y est, non ?

  • Francois

    Bonjour à toi.
    Cet article est très intéressant et bien écrit. Je suis étudiant et, en ce moment, en plein apprentissage du JS et parler des petites incohérences du langage n’est pas de refus tant c’est amusant (pas trop quand même).
    Pour le 0.1 + 0.2, JS n’est pas le seul à posséder ce « bug » (qui n’en est pas un) mais peut être un des rares à l’afficher si « fièrement » sans tronquer au xème 0.
    D’aileurs côté incohérences du JS, j’en ai encore quelques unes :
    pour les conversions implicites :
    !!0 donne false
    !!’0′ donne true !
    en effet si Boolean(0) vaut false, Boolean(‘0’) vaut true. Et comme les entrées utilisateurs sont des strings…

    Faire attention aussi :
    typeof(0.3) ‘Number’
    typeof(Number(0.3) )’Number’
    typeof(new Number(0.3)) ‘Object’

    • http://www.mathieurobin.com/ Mathieu

      Très intéressant ton commentaire, je ne connaissais pas la subtilité sur les booléens. J’y ferai référence si je fais un billet dessus.
      Et bien vu pour typeof(new Number(0.3)) ‘Object’, il est vrai qu’on peut courir droit dans le mur à cause de ça

  • http://tutos-django.com Guillaume

    Un article intéressant à propos du chiffre 0.2 a été écrit sur le blog de YUI :
    http://yuiblog.com/blog/2009/03/10/when-you-cant-count-on-your-numbers/

    D’autres exemples sont également mis en avant :)

    • http://www.mathieurobin.com/ Mathieu

      A regarder donc asap^^

Articles liés