Was ist der schnellste Weg, um String in JavaScript in Zahl umzuwandeln?

122

Beliebige Nummer, es ist Nummer. String sieht aus wie eine Zahl, es ist eine Zahl. Alles andere geht es NaN.

'a' => NaN
'1' => 1
1 => 1
Beatak
quelle
Was am schnellsten ist, hängt von den Optimierungen in einer bestimmten Implementierung zu einem bestimmten Zeitpunkt ab. Es gibt keinen objektiv "schnellsten" Weg.
Ich hasse Lazy
2
Was ist mit '1a'String zu tun ? Mit ' 1'einem? Mit anderen Worten, warum reichen Ihnen die meisten gängigen Methoden ( Number(x)und parseInt(x, 10)) nicht aus?
raina77ow
Ein früherer jsperf-Test: jsperf.com/converting-string-to-int/3
epascarello
Hier ein guter Leistungsvergleich der verschiedenen Methoden: jsben.ch/#/NnBKM
EscapeNetscape

Antworten:

191

Soweit ich weiß, gibt es vier Möglichkeiten.

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

Durch diesen schnellen Test, den ich gemacht habe, kommt es tatsächlich auf Browser an.

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

Implicit In 3 Browsern als am schnellsten markiert, aber der Code ist schwer zu lesen. Wählen Sie also, wie Sie möchten!

Beatak
quelle
7
Interessanterweise verwendet Google Analytics (der Teil, den Sie in Ihre Website einfügen) 1*für die Konvertierung von Datum in Nummer, ähnlich wie +oben. dh 1*new Date()eher als +new Date(). Möglicherweise ist es besser lesbar?
Matthew Wilcoxson
1
Ich denke, 1*wird bevorzugt, weil es weniger fehleranfällig ist. Eine unerwünschte baumelnde Variable zuvor +1ist kein Analysefehler. Es ist ein Trick ähnlich wie if (MYCONSTANT == myvar)in C.
Tomas
5
@beatak - Aktuelle Optimierungen scheinen native Methoden im Gegensatz zur impliziten Konvertierung zu bevorzugen. Ich werde für Number () in Chrome 37.0.2062.124 unter Windows Server 2008 R2 / 7 und ParseInt () in Firefox 30.0 am schnellsten, wobei implizit für beide die langsamste ist. Zum allgemeinen Vergleich können Sie auch in Betracht ziehen, String-Literal-Floats in den Test aufzunehmen. Ich vermute, dass sich die Reihenfolge in einigen Fällen ändern kann, da die Konvertierung von String in Float im Allgemeinen langsamer ist als die Konvertierung von String in Int. So wie der Test jetzt ist, kommt er mit einer Konvertierung von String zu Int davon, wenn Number () verwendet wird.
Nolo
1
Chrome 61.0.3163. Number () ist am schnellsten.
Dmitry Petukhov
70

Es gibt mindestens 5 Möglichkeiten, dies zu tun:

Wenn Sie nur in Ganzzahlen konvertieren möchten, ist ein weiterer schneller (und kurzer) Weg das Doppelbitweise nicht (dh die Verwendung von zwei Tilde-Zeichen):

z.B

~~x;

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

Die 5 gängigen Methoden, die ich bisher kenne, um eine Zeichenfolge in eine Zahl umzuwandeln, haben alle ihre Unterschiede (es gibt mehr bitweise Operatoren, die funktionieren, aber alle liefern das gleiche Ergebnis wie ~~ ). Diese JSFiddle zeigt die verschiedenen Ergebnisse, die Sie in der Debug-Konsole erwarten können: 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);
}

Debug-Konsole:

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

Das ~~x Version führt zu einer Zahl in "mehr" Fällen, in denen andere häufig dazu führen undefined, schlägt jedoch bei ungültiger Eingabe fehl (z. B. wird zurückgegeben, 0wenn die Zeichenfolge nach einer gültigen Zahl Zeichen enthält, die keine Zahlen sind).

Überlauf

Bitte beachten Sie: Bei ~~den anderen Konvertierungen können ganzzahlige Überläufe und / oder Bitkürzungen auftreten , nicht jedoch. Während es ungewöhnlich ist, so große Werte einzugeben, müssen Sie sich dessen bewusst sein. Beispiel aktualisiert, um viel größere Werte einzuschließen.

Einige Perf-Tests zeigen, dass der Standard parseIntund die parseFloatFunktionen tatsächlich die schnellsten Optionen sind, die vermutlich von Browsern stark optimiert wurden. Dies hängt jedoch von Ihren Anforderungen ab, da alle Optionen schnell genug sind : http://jsperf.com/best-of-string-to -Nummernumwandlung / 37

Dies hängt alles davon ab, wie die Perf-Tests konfiguriert sind, da einige zeigen, dass parseInt / parseFloat viel langsamer ist.

Meine Theorie lautet:

  • Lügen
  • Verdammte Linien
  • Statistiken
  • JSPerf Ergebnisse :)
Codierung weg
quelle
3
Seien Sie sehr vorsichtig bei Zahlen größer als 2147483647. Beispiel: ~~4294967296Rückgabe 0.
Joseph Goh
@JosephGoh: Wenn ich die Chance bekomme, werde ich die Ergebnisse um einen Int-Range-Überlauf erweitern. Wenn die Zahlen so groß sind, haben Sie im Allgemeinen eine ganz spezielle Schnittstelle, sodass Sie sich des Überlaufs bewusst sein müssen. Cheers
Gone Coding
@JosephGoh: Interessanterweise erhalten Sie in Chrome keine Nullen, sondern negative Zahlen nach dem vorzeichenbehafteten Maximalwert. Dann scheint es einfach, die zusätzlichen Bits zu löschen, wenn Sie den vorzeichenlosen int max -Wert überschreiten. zB "4999999999" => 705032703
Gone Coding
8

Stellen Sie dem +Operator den String voran.

console.log(+'a') // NaN
console.log(+'1') // 1
console.log(+1) // 1
Pratheep
quelle
7

Eine schnelle Möglichkeit, Zeichenfolgen in eine Ganzzahl umzuwandeln, besteht darin, eine bitweise oder wie folgt zu verwenden:

x | 0

Während es davon abhängt, wie es implementiert wird, sollte es theoretisch relativ schnell sein (mindestens so schnell wie +x), da es zuerst xin eine Zahl umgewandelt wird und dann ein sehr effizientes oder ausführt.

user3784814
quelle
Ja, aber ich glaube, diese Technik schneidet große ganze Zahlen ab, das ist ziemlich schlecht. Zu beachten ist, dass ich auch anstelle von Math.floor () verwendet werden kann, jedoch mit demselben Problem.
Jean
Hier ist ein jsperf verschiedener bitweiser Operatoren in Verbindung mit den Methoden in der ersten Antwort. Ich habe die Reihenfolge randomisiert, da ich festgestellt habe, dass einige Browser den nächsten Test basierend auf ähnlichem Code aus dem vorherigen Test optimieren würden. Im Gegensatz zum Top-Antwortenden fand ich, dass implizit die schlechteste Methode war.
Pluto
4

Hier ist eine einfache Möglichkeit: var num = Number (str); In diesem Beispiel ist str die Variable, die den String enthält. Sie können testen und sehen, wie es geöffnet funktioniert: Google Chrome-Entwicklertools. Gehen Sie dann zur Konsole und fügen Sie den folgenden Code ein. Lesen Sie die Kommentare, um besser zu verstehen, wie die Konvertierung durchgeführt wird.

// 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);
Edmundo
quelle
4

Ich finde das num * 1einfach, klar und funktioniert für ganze Zahlen und Gleitkommazahlen ...

Daniel Smith
quelle
3

Dies ist wahrscheinlich nicht so schnell, hat aber den zusätzlichen Vorteil, dass sichergestellt ist, dass Ihre Nummer mindestens einen bestimmten Wert (z. B. 0) oder höchstens einen bestimmten Wert hat:

Math.max(input, 0);

Wenn Sie einen Mindestwert sicherstellen müssen, tun Sie dies normalerweise

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

Math.max(..., 0) erspart Ihnen das Schreiben von zwei Aussagen.

Dan Dascalescu
quelle
Warum nicht verwenden Math.abs(input)? Außerdem werden Zeichenfolgen in positive Zahlen konvertiert und einige zusätzliche Zeichen gespeichert.
Aaron Gillion
1
@AaronGillion: Math.max (-5, 0) gibt 0 zurück; Math.abs (-5) gibt 5 zurück. Dies hängt vom Anwendungsfall ab, der sinnvoller ist.
Dan Dascalescu
1
Oh, hoppla, ja, mein Anwendungsfall war in der späten Nacht, in der ich diesen Kommentar schrieb, ganz anders.
Aaron Gillion
Wenn inputnicht in Zahl umgewandelt werden kann, erhalten SieNaN
Domas Mar
0

Sie können UnitOf verwenden , eine Mess- und Datentypkonvertierungsbibliothek, die wir gerade offiziell veröffentlicht haben! UnitOf ist superschnell, klein und kann jeden Datentyp effizient konvertieren, ohne jemals einen Fehler oder null / undefiniert auszulösen. Von Ihnen definierte Standardwerte oder die Standardeinstellungen von UnitOf werden zurückgegeben, wenn eine Konvertierung nicht erfolgreich ist.

//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.
Digidemic
quelle
0

Der schnellste Weg ist die Verwendung von -0:

const num = "12.34" - 0;
Arturas
quelle