Qual é a maneira mais rápida de converter String para Number em JavaScript?

122

Qualquer número, é número. String parece um número, é número. Tudo o resto, vai NaN.

'a' => NaN
'1' => 1
1 => 1
beatak
fonte
O que é mais rápido depende das otimizações em uma determinada implementação em um determinado momento. Não existe uma maneira objetiva "mais rápida".
Eu Odeio preguiçoso
2
O que deve ser feito com a '1a'string? Com ' 1'um? Em outras palavras, por que os métodos mais comuns para fazer isso ( Number(x)e parseInt(x, 10)) não são suficientes para você?
raina77ow
Um teste jsperf anterior: jsperf.com/converting-string-to-int/3
epascarello 12/12
aqui uma boa comparação de desempenho dos diferentes métodos: jsben.ch/#/NnBKM
EscapeNetscape

Respostas:

191

Existem quatro maneiras de fazê-lo, tanto quanto eu sei.

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

Por esse teste rápido que fiz, na verdade depende dos navegadores.

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

Implicit marcou o mais rápido em três navegadores, mas dificulta a leitura do código ... Então, escolha o que você quiser!

beatak
fonte
7
Curiosamente, o Google Analytics (a parte que você cola no seu site) usa 1*para a conversão de data em número, semelhante à +anterior. ou seja, em 1*new Date()vez de +new Date(). Possivelmente é mais legível?
Matthew Wilcoxson
1
Eu acho que 1*é preferido porque é menos propenso a erros. Uma variável dangling indesejada antes +1não é um erro de análise. É um truque semelhante ao uso if (MYCONSTANT == myvar)no C.
Tomas
5
@beatak - As otimizações atuais parecem favorecer métodos nativos em oposição à conversão implícita. Estou ficando mais rápido com Number () no Chrome 37.0.2062.124 no Windows Server 2008 R2 / 7 e ParseInt () no Firefox 30.0, sendo o implícito o mais lento para ambos. Além disso, você pode considerar incluir flutuadores literais de cadeia no teste para comparação geral. Meu palpite é que, em alguns casos, isso pode mudar a ordem, porque a conversão de string para float é geralmente mais lenta que a conversão de string para int. Do jeito que o teste está agora, ele está fugindo de uma string para conversão de int quando Number () é usado.
Nolo
1
Chrome 61.0.3163. Number () é o mais rápido de todos.
Dmitry Petukhov
70

Existem pelo menos 5 maneiras de fazer isso:

Se você deseja converter apenas em números inteiros, outra maneira rápida (e curta) é a não-bit a bit duplo (ou seja, usando dois caracteres til):

por exemplo

~~x;

Referência: http://james.padolsey.com/cool-stuff/double-bitwise-not/

As 5 maneiras comuns que conheço até agora para converter uma string em um número têm suas diferenças (existem mais operadores bit a bit que funcionam, mas todos dão o mesmo resultado ~~). Este JSFiddle mostra os diferentes resultados que você pode esperar no console de depuração: 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 depuração:

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

A ~~xversão resulta em um número em "mais" casos, onde outros geralmente resultam undefined, mas falha na entrada inválida (por exemplo, retornará 0se a sequência contiver caracteres não numéricos após um número válido).

Transbordar

Observe: Excesso de número inteiro e / ou truncamento de bits podem ocorrer com ~~, mas não as outras conversões. Embora seja incomum digitar valores tão grandes, você precisa estar ciente disso. Exemplo atualizado para incluir valores muito maiores.

Alguns testes Perf indicam que o padrão parseInte as parseFloatfunções são, na verdade, as opções mais rápidas, presumivelmente altamente otimizadas pelos navegadores, mas tudo depende da sua exigência, pois todas as opções são rápidas o suficiente : http://jsperf.com/best-of-string-to -número-conversão / 37

Tudo isso depende de como os testes perf são configurados, pois alguns mostram que parseInt / parseFloat é muito mais lento.

Minha teoria é:

  • Mentiras
  • Linhas danadas
  • Estatisticas
  • Resultados JSPerf :)
Gone Coding
fonte
3
Tenha muito cuidado com números maiores que 2147483647. Por exemplo: ~~4294967296retorna 0.
Joseph Goh
@ JosephphGoh: Quando eu tiver uma chance, estenderei os resultados para incluir o estouro de intervalo int. Geralmente, se os números são grandes, você tem uma interface muito especial, portanto, você deve estar ciente do estouro. Cheers
Gone Coding (
@ JosephphGoh: Curiosamente, no Chrome, você não obtém 0, obtém números negativos após o valor máximo assinado. Em seguida, parece simplesmente eliminar os bits extras quando você excede o valor int int não assinado. por exemplo "4999999999" => 705032703
Gone Coding
8

Prefixe a sequência com o +operador.

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

Uma maneira rápida de converter seqüências de caracteres em um número inteiro é usar um bit a bit ou, assim:

x | 0

Embora dependa de como é implementado, em teoria deve ser relativamente rápido (pelo menos tão rápido quanto +x), pois ele primeiro converterá xem um número e depois executará um ou muito eficiente.

user3784814
fonte
Sim, mas acredito que essa técnica trunque números inteiros grandes, o que é muito ruim. Note-se, também posso ser usado em vez de Math.floor (), mas com o mesmo problema.
19414 Jean
Aqui está um jsperf de vários operadores bit a bit em conjunto com os métodos da primeira resposta. Eu randomizei o pedido porque descobri que alguns navegadores otimizariam o próximo teste com base em código semelhante ao teste anterior. Ao contrário do que respondeu, achei que implícito era o pior método.
Plutão
4

Aqui está uma maneira simples de fazer isso: var num = Number (str); neste exemplo str é a variável que contém a string. Você pode testar e ver como ele funciona em aberto: ferramentas de desenvolvedor do Google chrome , acesse o console e cole o seguinte código. leia os comentários para entender melhor como a conversão é feita.

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

Acho que num * 1é simples, claro e funciona para números inteiros e flutuantes ...

Daniel Smith
fonte
3

Provavelmente não é tão rápido, mas tem o benefício adicional de garantir que seu número seja pelo menos um determinado valor (por exemplo, 0) ou, no máximo, um determinado valor:

Math.max(input, 0);

Se você precisa garantir um valor mínimo, normalmente faria

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

Math.max(..., 0) evita que você escreva duas instruções.

Dan Dascalescu
fonte
Por que não usar Math.abs(input)? Ele também converte seqüências de caracteres em números positivos e salva alguns caracteres extras.
Aaron Gillion #
1
@AaronGillion: Math.max (-5, 0) retornará 0; Math.abs (-5) retornará 5. Depende do caso de uso que faz mais sentido.
Dan Dascalescu
1
Opa, sim, meu caso de uso foi bem diferente durante a noite que escrevi esse comentário.
Aaron Gillion
Se inputnão pode ser convertido em número que você vai terNaN
Domas Mar
0

Você pode tentar usar o UnitOf , uma biblioteca de conversão de medidas e tipos de dados que acabamos de lançar oficialmente! O UnitOf é super rápido, pequeno e eficiente na conversão de qualquer tipo de dados sem nunca gerar um erro ou nulo / indefinido. Os valores padrão que você define ou os padrões do UnitOf são retornados quando uma conversão é malsucedida.

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

A maneira mais rápida é usar -0:

const num = "12.34" - 0;
Arturas
fonte