¿Cuál es la forma más rápida de convertir String a Number en JavaScript?

122

Cualquier número, es número. La cadena parece un número, es un número. Todo lo demás, va NaN.

'a' => NaN
'1' => 1
1 => 1
beatak
fuente
Lo que es más rápido depende de las optimizaciones en una implementación dada en un momento dado. No hay una forma objetivamente "más rápida".
Odio a los perezosos el
2
¿Qué se debe hacer con una '1a'cuerda? Con ' 1'uno? En otras palabras, ¿por qué los métodos más comunes para hacer eso ( Number(x)y parseInt(x, 10)) no son suficientes para usted?
raina77ow
Una prueba anterior de jsperf: jsperf.com/converting-string-to-int/3
epascarello
aquí una buena comparación de rendimiento de los diferentes métodos: jsben.ch/#/NnBKM
EscapeNetscape

Respuestas:

192

Hay 4 formas de hacerlo hasta donde yo sé.

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

Según esta prueba rápida que hice, en realidad depende de los navegadores.

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

Implicit marcó el más rápido en 3 navegadores, pero hace que el código sea difícil de leer ... ¡Así que elige lo que quieras!

beatak
fuente
77
Curiosamente, Google Analytics (la parte que pega en su sitio web) utiliza 1*para la conversión de fecha a número, que es similar a la +anterior. es decir, en 1*new Date()lugar de +new Date(). ¿Posiblemente es más legible?
Matthew Wilcoxson el
1
Creo que 1*es preferible porque es menos propenso a errores. Una variable colgante no deseada antes +1no es un error de análisis. Es un truco similar a usar if (MYCONSTANT == myvar)en C.
Tomás
55
@beatak: las optimizaciones actuales parecen favorecer los métodos nativos en lugar de la conversión implícita. Me estoy volviendo más rápido para Number () en Chrome 37.0.2062.124 en Windows Server 2008 R2 / 7 y ParseInt () en Firefox 30.0, siendo implícito el más lento para ambos. Además, puede considerar incluir flotantes de literal de cadena en la prueba para la comparación general. Supongo que puede cambiar el orden en algunos casos porque la conversión de cadena a flotante es generalmente más lenta que la conversión de cadena a int. Tal como está la prueba ahora, se está escapando con una conversión de cadena a int cuando se usa Number ().
Nolo
1
Chrome 61.0.3163. Number () es el más rápido de todos.
Dmitry Petukhov
70

Hay al menos 5 formas de hacer esto:

Si desea convertir solo a enteros, otra forma rápida (y corta) es el doble bit a bit (es decir, usando dos caracteres tilde):

p.ej

~~x;

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

Las 5 formas comunes que conozco hasta ahora para convertir una cadena en un número tienen sus diferencias (hay más operadores bit a bit que funcionan, pero todos dan el mismo resultado que ~~). Este JSFiddle muestra los diferentes resultados que puede esperar en la consola de depuración: 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);
}

Consola de depuración:

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 ~~xversión da como resultado un número en "más" casos, donde otros a menudo dan como resultado undefined, pero falla por una entrada no válida (por ejemplo, regresará 0si la cadena contiene caracteres que no son números después de un número válido).

Desbordamiento

Tenga en cuenta: puede ocurrir un desbordamiento de enteros y / o truncamiento de bits ~~, pero no con las otras conversiones. Si bien es inusual ingresar valores tan grandes, debe ser consciente de esto. Ejemplo actualizado para incluir valores mucho más grandes.

Algunas pruebas de rendimiento indican que el estándar parseInty las parseFloatfunciones son en realidad las opciones más rápidas, presumiblemente altamente optimizadas por los navegadores, pero todo depende de sus requisitos, ya que todas las opciones son lo suficientemente rápidas : http://jsperf.com/best-of-string-to -conversión-número / 37

Todo esto depende de cómo se configuren las pruebas de rendimiento, ya que algunos muestran que parseInt / parseFloat es mucho más lento.

Mi teoría es:

  • Mentiras
  • Líneas malditas
  • Estadísticas
  • Resultados JSPerf :)
Codificación ido
fuente
3
Tenga mucho cuidado con los números mayores que 2147483647. Por ejemplo: ~~4294967296devoluciones 0.
Joseph Goh el
@JosephGoh: Cuando tenga la oportunidad, extenderé los resultados para incluir el desbordamiento del rango int. En general, si los números son tan grandes, tiene una interfaz muy especial, por lo que deberá tener en cuenta el desbordamiento. Cheers
Gone Coding
@JosephGoh: Curiosamente, en Chrome, no obtienes 0, obtienes números negativos más allá del valor máximo firmado. Luego parece que simplemente se caen los bits adicionales cuando se excede el valor int max sin signo. por ejemplo, "4999999999" => 705032703
Codificación desaparecida el
8

Prefije la cadena con el +operador.

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

Una forma rápida de convertir cadenas a un entero es usar un bit a bit o, de esta manera:

x | 0

Si bien depende de cómo se implemente, en teoría debería ser relativamente rápido (al menos tan rápido como +x) ya que primero emitirá xun número y luego realizará un muy eficiente o.

usuario3784814
fuente
Sí, pero creo que esta técnica trunca los enteros grandes, eso es bastante malo. Cabe señalar que también se puede usar en lugar de Math.floor (), pero con el mismo problema.
Jean
Aquí hay una jsperf de varios operadores bit a bit junto con los métodos en la primera respuesta. Aleatoricé el pedido porque descubrí que algunos navegadores optimizarían la próxima prueba basada en un código similar de la prueba anterior. A diferencia del que responde mejor, descubrí que el método más implícito era el peor.
Plutón el
4

Aquí hay una manera simple de hacerlo: var num = Number (str); en este ejemplo, str es la variable que contiene la cadena. Puede probar y ver cómo funciona abierto: herramientas para desarrolladores de Google Chrome , luego vaya a la consola y pegue el siguiente código. lea los comentarios para comprender mejor cómo se realiza la conversión.

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

Me parece que num * 1es simple, claro y funciona para enteros y flotantes ...

Daniel Smith
fuente
3

Probablemente esto no sea tan rápido, pero tiene el beneficio adicional de asegurarse de que su número tenga al menos un cierto valor (por ejemplo, 0), o como máximo un cierto valor:

Math.max(input, 0);

Si necesita asegurar un valor mínimo, generalmente lo haría

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

Math.max(..., 0) te salva de escribir dos declaraciones.

Dan Dascalescu
fuente
¿Por qué no usar Math.abs(input)? También convierte cadenas en números positivos y guarda algunos caracteres adicionales.
Aaron Gillion
1
@AaronGillion: Math.max (-5, 0) devolverá 0; Math.abs (-5) devolverá 5. Depende del caso de uso que tenga más sentido.
Dan Dascalescu
1
Oh, vaya, sí, mi caso de uso fue muy diferente durante cualquier noche que escribí ese comentario.
Aaron Gillion
Si inputno se puede convertir al número que obtendráNaN
Domas Mar
0

¡Puede intentar usar UnitOf , una biblioteca de conversión de medidas y tipos de datos que acabamos de lanzar oficialmente! UnitOf es súper rápido, pequeño y eficiente en la conversión de cualquier tipo de datos sin arrojar un error o nulo / indefinido. Los valores predeterminados que defina o los valores predeterminados de UnitOf se devuelven cuando una conversión no tiene éxito.

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

La forma más rápida es usar -0:

const num = "12.34" - 0;
Arturas
fuente