Quel est le moyen le plus rapide de convertir une chaîne en nombre en JavaScript?


122

N'importe quel nombre, c'est un numéro. La chaîne ressemble à un nombre, c'est un nombre. Tout le reste, ça passe NaN.

'a' => NaN
'1' => 1
1 => 1

Ce qui est le plus rapide dépend des optimisations dans une implémentation donnée à un moment donné. Il n'y a pas de moyen objectivement «le plus rapide».
Je déteste paresseux

2
Que faut-il faire avec la '1a'chaîne? Avec ' 1'un? En d'autres termes, pourquoi les méthodes les plus courantes pour faire cela ( Number(x)et parseInt(x, 10)) ne vous suffisent pas?
raina77ow


voici une bonne comparaison des performances des différentes méthodes: jsben.ch/#/NnBKM
EscapeNetscape

Réponses:


192

Autant que je sache, il y a 4 façons de le faire.

Number(x);
parseInt(x, 10);
parseFloat(x);
+x;

Par ce test rapide que j'ai fait, cela dépend en fait des navigateurs.

http://jsperf.com/best-of-string-to-number-conversion/2

Implicit marqué le plus rapide sur 3 navigateurs, mais cela rend le code difficile à lire… Alors choisissez ce que vous en avez envie!


7
Fait intéressant, Google Analytics (la partie que vous collez dans votre site Web) utilise 1*pour la conversion de date en nombre, ce qui est similaire à ce qui +précède. c'est-à-dire 1*new Date()plutôt que +new Date(). Peut-être est-ce plus lisible?
Matthew Wilcoxson

1
Je pense que 1*c'est préféré car il est moins sujet aux erreurs. Une variable pendante indésirable avant +1n'est pas une erreur d'analyse. C'est une astuce similaire à l'utilisation if (MYCONSTANT == myvar)dans C.
Tomas

5
@beatak - Les optimisations actuelles semblent favoriser les méthodes natives par opposition à la conversion implicite. Je reçois le plus rapide pour Number () dans Chrome 37.0.2062.124 sur Windows Server 2008 R2 / 7 et ParseInt () dans Firefox 30.0, implicite étant le plus lent pour les deux. En outre, vous pouvez envisager d'inclure des flottants littéraux de chaîne dans le test pour une comparaison générale. Je suppose que cela peut changer l'ordre dans certains cas, car la conversion chaîne en flottant est généralement plus lente que la conversion chaîne en int. La façon dont le test est maintenant, il s'en tire avec une conversion de chaîne en int lorsque Number () est utilisé.
Nolo le

1
Chrome 61.0.3163. Number () est le plus rapide de tous.
Dmitry Petukhov

70

Il existe au moins 5 façons de procéder:

Si vous souhaitez convertir uniquement en nombres entiers, un autre moyen rapide (et court) est le non double bit (c'est-à-dire en utilisant deux caractères tilde):

par exemple

~~x;

Référence: http://james.padolsey.com/cool-stuff/double-bitwise-not/

Les 5 méthodes courantes que je connais jusqu'à présent pour convertir une chaîne en un nombre ont toutes leurs différences (il y a plus d'opérateurs au niveau du bit qui fonctionnent, mais ils donnent tous le même résultat que ~~). Ce JSFiddle montre les différents résultats auxquels vous pouvez vous attendre dans la console de débogage: http://jsfiddle.net/TrueBlueAussie/j7x0q0e3/22/

var values = ["123",
          undefined,
          "not a number",
          "123.45",
          "1234 error",
          "2147483648",
          "4999999999"
          ];

for (var i = 0; i < values.length; i++){
    var x = values[i];

    console.log(x);
    console.log(" Number(x) = " + Number(x));
    console.log(" parseInt(x, 10) = " + parseInt(x, 10));
    console.log(" parseFloat(x) = " + parseFloat(x));
    console.log(" +x = " + +x);
    console.log(" ~~x = " + ~~x);
}

Console de débogage:

123
  Number(x) = 123
  parseInt(x, 10) = 123
  parseFloat(x) = 123
  +x = 123
  ~~x = 123
undefined
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
null
  Number(x) = 0
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = 0
  ~~x = 0
"not a number"
  Number(x) = NaN
  parseInt(x, 10) = NaN
  parseFloat(x) = NaN
  +x = NaN
  ~~x = 0
123.45
  Number(x) = 123.45
  parseInt(x, 10) = 123
  parseFloat(x) = 123.45
  +x = 123.45
  ~~x = 123
1234 error
  Number(x) = NaN
  parseInt(x, 10) = 1234
  parseFloat(x) = 1234
  +x = NaN
  ~~x = 0
2147483648
  Number(x) = 2147483648
  parseInt(x, 10) = 2147483648
  parseFloat(x) = 2147483648
  +x = 2147483648
  ~~x = -2147483648
4999999999
  Number(x) = 4999999999
  parseInt(x, 10) = 4999999999
  parseFloat(x) = 4999999999
  +x = 4999999999
  ~~x = 705032703

La ~~xversion donne un nombre dans les cas «plus», où d'autres aboutissent souvent undefined, mais échoue pour une entrée non valide (par exemple, elle retournera 0si la chaîne contient des caractères non numériques après un nombre valide).

Débordement

Remarque: un dépassement d'entier et / ou une troncature de bits peuvent se produire avec ~~, mais pas avec les autres conversions. Bien qu'il soit inhabituel d'entrer des valeurs aussi importantes, vous devez en être conscient. Exemple mis à jour pour inclure des valeurs beaucoup plus grandes.

Certains tests Perf indiquent que le standard parseIntet les parseFloatfonctions sont en fait les options les plus rapides, probablement hautement optimisées par les navigateurs, mais tout dépend de vos besoins car toutes les options sont assez rapides : http://jsperf.com/best-of-string-to -nombre-conversion / 37

Tout dépend de la façon dont les tests de performance sont configurés, car certains montrent que parseInt / parseFloat est beaucoup plus lent.

Ma théorie est:

  • Mensonges
  • Darn lignes
  • Statistiques
  • Résultats JSPerf :)

3
Soyez vraiment prudent pour les nombres supérieurs à 2147483647. ex: ~~4294967296renvoie 0.
Joseph Goh

@JosephGoh: Quand j'en aurai l'occasion, j'étendrai les résultats pour inclure le débordement de la plage int. En règle générale, si les chiffres sont si grands, vous avez une interface très spéciale, vous devez donc être conscient du débordement. Cheers
Gone Coding

@JosephGoh: Fait intéressant, dans Chrome, vous n'obtenez pas de 0, vous obtenez des nombres négatifs au-delà de la valeur maximale signée. Ensuite, il semble simplement supprimer les bits supplémentaires lorsque vous dépassez la valeur max. eg "4999999999" => 705032703
Codage

8

Préfixez la chaîne avec l' +opérateur.

console.log(+'a') // NaN
console.log(+'1') // 1
console.log(+1) // 1

7

Un moyen rapide de convertir des chaînes en entier est d'utiliser un bit au niveau du bit ou, comme ceci:

x | 0

Bien que cela dépende de la façon dont il est implémenté, en théorie, il devrait être relativement rapide (au moins aussi rapide que +x) car il sera d'abord converti xen un nombre, puis effectuera un ou.


Oui, mais je crois que cette technique tronque de grands entiers, c'est assez mauvais. Pour être noté, je peux également être utilisé à la place de Math.floor (), mais avec le même problème.
Jean

Voici un jsperf de divers opérateurs binaires en conjonction avec les méthodes de la première réponse. J'ai randomisé la commande car j'ai constaté que certains navigateurs optimiseraient le prochain test en fonction d'un code similaire du test précédent. Contrairement au premier répondant, j'ai trouvé que l'implicite était la pire méthode.
Pluto

4

Voici un moyen simple de le faire: var num = Number (str); dans cet exemple, str est la variable qui contient la chaîne. Vous pouvez tester et voir comment cela fonctionne ouvert: Outils de développement Google Chrome , puis accédez à la console et collez le code suivant. lisez les commentaires pour mieux comprendre comment la conversion est effectuée.

// Here Im creating my variable as a string
var str = "258";


// here im printing the string variable: str
console.log ( str );


// here Im using typeof , this tells me that the variable str is the type: string
console.log ("The variable str is type: " + typeof str);


// here is where the conversion happens
// Number will take the string in the parentesis and transform it to a variable num as type: number
var num = Number(str);
console.log ("The variable num is type: " + typeof num);

4

Je trouve que num * 1c'est simple, clair et fonctionne pour les entiers et les flottants ...


3

Ce n'est probablement pas si rapide, mais a l'avantage supplémentaire de s'assurer que votre numéro a au moins une certaine valeur (par exemple 0), ou au plus une certaine valeur:

Math.max(input, 0);

Si vous devez garantir une valeur minimale, vous feriez généralement

var number = Number(input);
if (number < 0) number = 0;

Math.max(..., 0) vous évite d'écrire deux déclarations.


Pourquoi ne pas l'utiliser Math.abs(input)? Il convertit également les chaînes en nombres positifs et enregistre quelques caractères supplémentaires.
Aaron Gillion

1
@AaronGillion: Math.max (-5, 0) renverra 0; Math.abs (-5) renverra 5. Cela dépend du cas d'utilisation qui a plus de sens.
Dan Dascalescu

1
Oh, oups, oui, mon cas d'utilisation était très différent pendant toute la nuit où j'ai écrit ce commentaire.
Aaron Gillion

Si inputvous ne pouvez pas être converti en nombre, vous obtiendrezNaN
Domas

0

Vous pouvez essayer d'utiliser UnitOf , une bibliothèque de conversion de types de mesures et de données que nous venons de publier officiellement! UnitOf est super rapide, de petite taille et efficace pour convertir n'importe quel type de données sans jamais générer d'erreur ou null / undefined. Les valeurs par défaut que vous définissez ou les valeurs par défaut de UnitOf sont renvoyées lorsqu'une conversion échoue.

//One liner examples
UnitOf.DataType("12.5").toFloat(); //12.5 of type Float is returned. 0 would be returned if conversion failed.
UnitOf.DataType("Not A Num").toInt(10); //10 of type Int is returned as the conversion failed.

//Or as a variable
var unit = UnitOf.DataType("12.5");
unit.toInt(5); //12.5 of type Float is returned. 5 would be returned if the conversion failed.
unit.toFloat(8); // 12 of type Int is returned. 8 would be returned if the conversion failed.

0

Le moyen le plus rapide est d'utiliser -0:

const num = "12.34" - 0;
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.