Qual è il modo più veloce per convertire una stringa in un numero in JavaScript?


122

Qualsiasi numero, è un numero. La stringa sembra un numero, è un numero. Tutto il resto va NaN.

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

Ciò che è più veloce dipende dalle ottimizzazioni in una data implementazione in un dato momento. Non esiste un modo oggettivamente "più veloce".
I Hate Lazy

2
Cosa si dovrebbe fare con lo '1a'spago? Con ' 1'uno? In altre parole, perché i metodi più comuni per farlo ( Number(x)e parseInt(x, 10)) non sono sufficienti per te?
raina77ow


ecco un buon confronto delle prestazioni dei diversi metodi: jsben.ch/#/NnBKM
EscapeNetscape

Risposte:


192

Ci sono 4 modi per farlo per quanto ne so.

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

Da questo rapido test che ho fatto, in realtà dipende dai browser.

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

Implicit contrassegnato come il più veloce su 3 browser, ma rende il codice difficile da leggere ... Quindi scegli quello che preferisci!


7
È interessante notare che Google Analytics (la parte che incolli nel tuo sito web) utilizza 1*per la conversione da data a numero, che è simile a quanto +sopra. cioè 1*new Date()piuttosto che +new Date(). Forse è più leggibile?
Matthew Wilcoxson

1
Penso che 1*sia preferito perché è meno soggetto a errori. Una variabile penzolante indesiderata prima +1non è un errore di analisi. È un trucco simile all'utilizzo if (MYCONSTANT == myvar)in C.
Tomas

5
@beatak - Le attuali ottimizzazioni sembrano favorire i metodi nativi rispetto alla conversione implicita. Sto diventando più veloce per Number () in Chrome 37.0.2062.124 su Windows Server 2008 R2 / 7 e ParseInt () in Firefox 30.0 con implicito che è il più lento per entrambi. Inoltre, potresti prendere in considerazione l'inclusione di valori letterali stringa in virgola mobile nel test per il confronto generale. La mia ipotesi è che in alcuni casi possa cambiare l'ordine perché la conversione da stringa a float è generalmente più lenta della conversione da stringa a int. Il modo in cui il test è ora, sta andando via con una conversione da stringa a int quando viene utilizzato Number ().
Nolo,

1
Chrome 61.0.3163. Number () è il più veloce di tutti.
Dmitry Petukhov

70

Ci sono almeno 5 modi per farlo:

Se vuoi convertire solo in numeri interi, un altro modo veloce (e breve) è il doppio bit per non (cioè usando due caratteri tilde):

per esempio

~~x;

Riferimento: http://james.padolsey.com/cool-stuff/double-bitwise-not/

I 5 modi comuni che conosco finora per convertire una stringa in un numero hanno tutti le loro differenze (ci sono più operatori bit per bit che funzionano, ma danno tutti lo stesso risultato di ~~). Questo JSFiddle mostra i diversi risultati che puoi aspettarti nella console di debug: 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 di debug:

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 ~~xversione undefinedrestituisce un numero in "più" casi, in cui altri spesso risultano , ma fallisce per input non valido (ad esempio, restituirà 0se la stringa contiene caratteri non numerici dopo un numero valido).

straripamento

Nota: con ~~le altre conversioni possono verificarsi overflow di numeri interi e / o troncamenti di bit . Sebbene sia insolito inserire valori così grandi, è necessario esserne consapevoli. Esempio aggiornato per includere valori molto più grandi.

Alcuni test Perf indicano che lo standard parseInte le parseFloatfunzioni sono in realtà le opzioni più veloci, presumibilmente altamente ottimizzate dai browser, ma tutto dipende dalle tue esigenze poiché tutte le opzioni sono abbastanza veloci : http://jsperf.com/best-of-string-to -numero conversione / 37

Tutto dipende da come sono configurati i test perf poiché alcuni mostrano parseInt / parseFloat per essere molto più lenti.

La mia teoria è:

  • Bugie
  • Maledette linee
  • statistica
  • Risultati JSPerf :)

3
Fai molta attenzione per i numeri maggiori di 2147483647. Ad esempio: ~~4294967296ritorna 0.
Joseph Goh

@ JosephGoh: quando avrò la possibilità estenderò i risultati per includere l'overflow dell'intervallo int. In generale, se i numeri sono così grandi, hai un'interfaccia molto speciale in corso, quindi dovresti essere consapevole dell'overflow. Cheers
Gone Coding

@JosephGoh: È interessante notare che in Chrome, non ottieni 0, ottieni numeri negativi oltre il valore massimo con segno. Quindi sembra semplicemente eliminare i bit extra quando si supera il valore massimo int senza segno. ad es. "4999999999" => 705032703
Gone Coding

8

Prefisso la stringa con l' +operatore.

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

7

Un modo veloce per convertire le stringhe in un numero intero è usare un bit per bit o, in questo modo:

x | 0

Sebbene dipenda da come è implementato, in teoria dovrebbe essere relativamente veloce (almeno veloce quanto +x) poiché prima verrà lanciato xsu un numero e quindi eseguirà un o molto efficiente.


Sì, ma credo che questa tecnica troncare interi grandi, che è piuttosto brutto. Da notare, posso anche essere utilizzato al posto di Math.floor (), ma con lo stesso problema.
Jean

Ecco un jsperf di vari operatori bit per bit in combinazione con i metodi nella prima risposta. Ho randomizzato l'ordine perché ho scoperto che alcuni browser avrebbero ottimizzato il test successivo in base a codice simile del test precedente. A differenza del miglior risponditore, ho scoperto che implicito era il metodo peggiore.
Plutone

4

Ecco un modo semplice per farlo: var num = Number (str); in questo esempio str è la variabile che contiene la stringa. Puoi testarlo e vedere come funziona aperto: strumenti per sviluppatori di Google Chrome , quindi vai alla console e incolla il seguente codice. leggi i commenti per capire meglio come viene eseguita la conversione.

// 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

Trovo che num * 1sia semplice, chiaro e funzioni per interi e float ...


3

Probabilmente non è così veloce, ma ha il vantaggio aggiuntivo di assicurarsi che il tuo numero sia almeno un certo valore (ad esempio 0), o al massimo un certo valore:

Math.max(input, 0);

Se devi assicurarti un valore minimo, di solito lo faresti

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

Math.max(..., 0) ti evita di scrivere due dichiarazioni.


Perché non usare Math.abs(input)? Converte anche le stringhe in numeri positivi e salva alcuni caratteri extra.
Aaron Gillion

1
@AaronGillion: Math.max (-5, 0) restituirà 0; Math.abs (-5) restituirà 5. Dipende dal caso d'uso che ha più senso.
Dan Dascalescu

1
Oh, whoops, sì, il mio caso d'uso è stato molto diverso durante la tarda notte in cui ho scritto quel commento.
Aaron Gillion

Se inputnon può essere convertito in numero, otterraiNaN
Domas Mar

0

Puoi provare a utilizzare UnitOf , una libreria di misurazione e conversione del tipo di dati che abbiamo appena rilasciato ufficialmente! UnitOf è super veloce, di piccole dimensioni ed efficiente nel convertire qualsiasi tipo di dati senza mai generare un errore o null / undefined. I valori predefiniti definiti dall'utente o i valori predefiniti di UnitOf vengono restituiti quando una conversione non riesce.

//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

Il modo più veloce è usare -0:

const num = "12.34" - 0;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.