Javascript parseInt () com zeros à esquerda

120

A função parseInt do Javascript não parece funcionar completamente.

parseInt("01") returns 1
parseInt("02") returns 2
parseInt("03") returns 3
parseInt("04") returns 4
parseInt("05") returns 5
parseInt("06") returns 6
parseInt("07") returns 7
parseInt("08") returns 0
parseInt("09") returns 0

Você não pode explicar isso. De uma chance. (jsFiddle)

Editar Desde que esta pergunta foi feita e respondida, o "recurso" de padronizar para raiz octal foi descontinuado. [ 1 ] [ 2 ]

salvador
fonte
29
você deve estar brincando
georg
6
You can't explain that. Sim, você pode => developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…
Rocket Hazmat
3
Desde as idades, qualquer número começando com 0 representa OCTAL e 0x representa Hexa-Decimal. Acredito que isso seja universal para todos os idiomas, mas, novamente, posso estar errado.
Selvakumar Arumugam
3
Para sua informação: jsFiddle , é melhor testador de JavaScript online do que w3schools.com/jsref/tryit.asp .
Rocket Hazmat
2
@JohnHartsock Sim, é porque ambos estávamos nesta postagem stackoverflow.com/questions/8761997/…
savinger

Respostas:

181

Isso ocorre porque se um número começa com um '0', ele é tratado como base 8 (octal).

Você pode forçar a base passando a base como o segundo parâmetro.

parseInt("09", 10) // 9

De acordo com a documentação , o segundo parâmetro é opcional, mas nem sempre é considerado 10, como você pode ver no seu exemplo.

Foguete Hazmat
fonte
1
sim, mas se for considerado octal, deve retornar 11 para 09 em vez de 0.
Peeyush Kushwaha
2
@PeeyushKushwaha: O contrário. 11na base 8 está 9na base 10. 09não é um número de base 8 válido.
Foguete Hazmat de
Mas eu quero 09 após o parseInt, há alguma maneira de contornar
Pardeep Jain
39

As chamadas para parseIntdevem sempre especificar uma base no segundo argumento:

parseInt("08", 10);

Versões anteriores de JavaScript tratam strings começando com 0como octal (quando nenhuma base é especificada) e nem 08nem09 são números octais válidos.

Da documentação do Mozilla :

Se radix for indefinido ou 0, JavaScript assume o seguinte:

  • Se a string de entrada começar com "0x" ou "0X", a raiz é 16 (hexadecimal).
  • Se a string de entrada começar com "0", a raiz é oito (octal). Este recurso não é padrão e algumas implementações deliberadamente não o suportam (em vez de usar o radical 10). Por esse motivo, sempre especifique uma raiz ao usar parseInt .
  • Se a string de entrada começar com qualquer outro valor, a raiz será 10 (decimal).

Se o primeiro caractere não puder ser convertido em um número, parseInt retornará NaN.

E a partir do padrão ECMAScript 3 :

Quando a raiz é 0 ou indefinida e o número da string começa com um dígito 0 não seguido por um x ou X , a implementação pode, a seu critério, interpretar o número como octal ou como decimal. As implementações são encorajadas a interpretar os números, neste caso, como decimais.

A versão mais recente do JavaScript ( ECMAScript 5 ) abandona esse comportamento , mas você ainda deve especificar a raiz para satisfazer os navegadores mais antigos.

Wayne
fonte
Uma vez que isso está obsoleto, no futuro você ficaria bem em usar zeros à esquerda, não é?
Pacerier
15

Existe um parâmetro Radix

parseInt(value, base)

Onde a base é o radical.

Neste caso, você está avaliando números de base 10 (decimais), portanto, use

parseInt(value, 10);
John Hartsock
fonte
4

Isso não parece ser totalmente válido em novos navegadores. O Internet Explorer 9 e 10 retornará 8 se você executar 'parseInt ("08")', enquanto o Internet Explorer 8 e as versões anteriores retornarão 0 (o IE10 no modo quirks também retornará 0).

A versão mais recente do Chrome também retorna 8, então eles devem ter mudado a interpretação recentemente.

Maffelu
fonte
Sim, o comportamento mudou. Vou atualizar minha resposta. developer.mozilla.org/en-US/docs/JavaScript/Reference/…
Wayne
1
Sim, a versão mais recente do Firefox e do Chrome não tem problemas agora.
mythicalcoder
3

Este problema está obsoleto agora. Mas você ainda pode usar radix in parseIntpara converter o número de outras bases na base 10. Por exemplo,

var baseTwoNumber = parseInt('0010001', 2);

retorna 17(que é base 10 de 0010001).

Muhammad Imran
fonte
0

Dica: como você já sabe quando o padrão para octal foi preterido. Aqui está como você corrigiria em navegadores legados

// ES-5 15.1.2.2
if (parseInt('08') !== 8 || parseInt('0x16') !== 22) {
    parseInt = (function (origParseInt) {
        var hexRegex = /^0[xX]/;
        return function parseIntES5(str, radix) {
            str = String(str).trim();
            if (!Number(radix)) {
                radix = hexRegex.test(str) ? 16 : 10;
            }
            return origParseInt(str, radix);
        };
    }(parseInt));
}
Sem fim
fonte
PS: se você usar apenas um número constante com um zero à esquerda (em vez de uma string), ele ainda será tratado como base 8 em todos os navegadores atuais.
Agamemnus,
0

O problema parece ter mudado agora na maioria dos navegadores.

Firefox 51.0.1 (64 bits)

parseInt("09")   // 9

Chrome 55.0.2883.95 (64 bits)

parseInt("09")   // 9

Safari 10.0 (12602.1.50.0.10)

parseInt("09")   // 9

=====

Prática Recomendada

Dito isso, apenas para ficar no lado mais seguro e evitar problemas, use o parâmetro base / radix conforme sugerido na resposta aceita .

parseInt("09", 10)    // 9

Teste extra

Eu só queria testar isso também, se o argumento não for uma string. Chrome e Safari dão o resultado exato. O Firefox também retorna um resultado adequado, mas com um aviso.

parseInt(09)     // 9. (Warning: SyntaxError: 09 is not a legal ECMA-262 octal constant)
codificador mítico
fonte
Se o valor começar com 0 e for um número, parseInt ainda usará a base 8. Tente parseInt (020)
sirrocco
Sim. Eu até apontei para a resposta sugerida. E eu conheço as práticas recomendadas e recursos ruins a evitar. Portanto, também dei a prática recomendada em minha resposta.
mythicalcoder