Como verificar se uma variável é um número inteiro em JavaScript?

405

Como verifico se uma variável é um número inteiro em JavaScript e emito um alerta se não for? Eu tentei isso, mas não funciona:

<html>
    <head>
        <script type="text/javascript">
            var data = 22;
            alert(NaN(data));
        </script>
    </head>
</html>
JBa
fonte
2
Uma possibilidade aqui é usar parseInt.
Paul
2
jsben.ch/#/htLVw - uma referência para as formas comuns de fazer isso
EscapeNetscape
Todas as respostas aqui estão realmente desatualizadas. Hoje, eu recomendo Number.isIntegerseguir a maneira menos invasiva.
Benjamin Gruenbaum
@ Benjamim, e se o número for uma string que possa ser convertida em um número inteiro? e no HTML tudo é uma string .. então Number.isInteger ("69") é falso
joedotnot

Respostas:

344

Use o operador === ( igualdade estrita ) como abaixo,

if (data === parseInt(data, 10))
    alert("data is integer")
else
    alert("data is not an integer")
pranag
fonte
95
isso conta NaN como um número inteiro. também tem um desempenho pior contra o meu método. jsperf.com/numbers-and-integers
Blake Regalia
2
se você executar o seu exemplo através do código acima, ele alerta a como um número inteiro e o outro como não um número inteiro, como é o caso ... no caso de NaN também o tipo de NaN é diferente do tipo do valor de retorno pareInt () .....
pranag
11
você poderia elaborar um pouco? o "exemplo" está apenas demonstrando que o uso de parseInt produz um desempenho pior do que o uso do operador typeof keyword e modulus. mas eu vejo o que você quer dizer agora sobre (NaN = NaN!)
Blake Regalia
4
@connorbode em javascript todos os números têm o mesmo tipo (não há float ou double), de modo que 2.0 === 2desde o decimal desnecessária é apenas uma representação diferente do mesmo número, portanto, parseInt(2.0) === 2.0é equivalente ao parseInt(2) === 2que é verdade
Michael Theriot
11
@BlakeRegalia: Apesar de ser rápido o seu método não passar todos os valores possíveis de esta resposta: stackoverflow.com/a/14794066/843732
C00000FD
506

Isso depende, você também deseja converter cadeias de caracteres como números inteiros em potencial?

Isso fará:

function isInt(value) {
  return !isNaN(value) && 
         parseInt(Number(value)) == value && 
         !isNaN(parseInt(value, 10));
}

Com operações Bitwise

Análise e verificação simples

function isInt(value) {
  var x = parseFloat(value);
  return !isNaN(value) && (x | 0) === x;
}

Curto-circuito e salvando uma operação de análise:

function isInt(value) {
  if (isNaN(value)) {
    return false;
  }
  var x = parseFloat(value);
  return (x | 0) === x;
}

Ou talvez ambos de uma só vez:

function isInt(value) {
  return !isNaN(value) && (function(x) { return (x | 0) === x; })(parseFloat(value))
}

Testes:

isInt(42)        // true
isInt("42")      // true
isInt(4e2)       // true
isInt("4e2")     // true
isInt(" 1 ")     // true
isInt("")        // false
isInt("  ")      // false
isInt(42.1)      // false
isInt("1a")      // false
isInt("4e2a")    // false
isInt(null)      // false
isInt(undefined) // false
isInt(NaN)       // false

Aqui está o violino: http://jsfiddle.net/opfyrqwp/28/

atuação

Os testes revelam que a solução de curto-circuito tem o melhor desempenho (ops / s).

// Short-circuiting, and saving a parse operation
function isInt(value) {
  var x;
  if (isNaN(value)) {
    return false;
  }
  x = parseFloat(value);
  return (x | 0) === x;
}

Aqui está uma referência: http://jsben.ch/#/htLVw

Se você gosta de uma forma mais curta e obtusa de curto-circuito:

function isInt(value) {
  var x;
  return isNaN(value) ? !1 : (x = parseFloat(value), (0 | x) === x);
}

Claro, eu sugiro deixar o minifier cuidar disso.

krisk
fonte
4
@krisk - Votado para várias soluções. Também realizou um teste rápido nas quatro variantes que você forneceu: jsperf.com/tfm-is-integer - e determinou que a solução de curto-circuito tem o melhor desempenho.
Tfmontague
11
Ele está retornando falso em 2099999999999999: - (
jkucharovic 26/06
11
@jkucharovic o operador OR bit a bit é o culpado. O uso da versão não bit a bit retornará true.
krisk
11
Isso faz '2'. avaliar a verdade
cyberwombat
11
@cyberwombat bem que é um número decimal 2,0 :-)
Kuba Beránek
120

Supondo que você não saiba nada sobre a variável em questão, siga esta abordagem:

if(typeof data === 'number') {
    var remainder = (data % 1);
    if(remainder === 0) {
        // yes, it is an integer
    }
    else if(isNaN(remainder)) {
        // no, data is either: NaN, Infinity, or -Infinity
    }
    else {
        // no, it is a float (still a number though)
    }
}
else {
    // no way, it is not even a number
}

Simplificando:

if(typeof data==='number' && (data%1)===0) {
    // data is an integer
}
Blake Regalia
fonte
8
O que você quer dizer? Isso verifica tipos de dados em javascript, "1.0"é uma sequência e, portanto, não é um número. Caso contrário 1, será o valor de uma variável se você a definir assim var my_var=1.0;, que é corretamente identificado por esta função como um número inteiro.
Blake Regalia
4
Em breve, Number.isInteger()vai funcionar ... até então, esta é uma boa maneira de fazê-lo
Claudiu
Number.isInteger não funciona para mim. Eu devo estar fazendo algo errado. A solução de Blake% 1 funciona perfeitamente.
Mcmacerson # 21/17
104

Number.isInteger() parece ser o caminho a percorrer.

A MDN também forneceu o seguinte polyfill para navegadores que não suportam Number.isInteger(), principalmente todas as versões do IE.

Link para a página MDN

Number.isInteger = Number.isInteger || function(value) {
    return typeof value === "number" && 
           isFinite(value) && 
           Math.floor(value) === value;
};
Walter Roman
fonte
2
MDN tem o teste em 9007199254740992 removido
Bernhard DOBLER
2
Essa é a resposta mais direta e "correta". Quero dizer, o JavaScript já tem o método para verificar se há número inteiro. Não há necessidade de escrever um novo. isNaN () testa numericidade, não número inteiro.
globewalldesk
66

Você pode verificar se o número tem um restante:

var data = 22;

if(data % 1 === 0){
   // yes it's an integer.
}

Lembre-se, se sua entrada também pode ser texto e você deseja verificar primeiro, não é, então pode verificar o tipo primeiro:

var data = 22;

if(typeof data === 'number'){
     // yes it is numeric

    if(data % 1 === 0){
       // yes it's an integer.
    }
}
Não
fonte
3
@ Erwinus: Execute 0 % 1 === 0no console. Retorna truecomo 0 % 1retornos 0.
Nope
Você experimentá-lo no IE ;-)
Codebeat
11
@ Erwinus: 0 % 1retorna 0no modo de compatibilidade IE9, IE8 e IE7.
Não
Experimente em um IE antigo. além disso, é sempre uma boa maneira de programar verificar o zero e não depender do navegador o que fazer.
Codebeat
62
@ Erwinus: Acho que você confundiu seus fatos. Um erro de divisão por zero é causado quando você divide por zero e não quando você divide zero por um número. Nada a ver com a versão do IE.
Nope
22

Você pode usar uma expressão regular simples:

function isInt(value) {
    var er = /^-?[0-9]+$/;
    return er.test(value);
}
Marcio Mazzucato
fonte
15

Primeiro, NaN é um "número" (sim, eu sei que é estranho, apenas role com ele), e não uma "função".

Você precisa verificar se o tipo da variável é um número e, para verificar o número inteiro, eu usaria o módulo.

alert(typeof data === 'number' && data%1 == 0);
Phil
fonte
2
deve ser: alert (typeof data == 'number' && (data == 0 || data% 1 == 0)); para evitar a divisão por zero.
Codebeat
19
@Erwinus 0% 1 ainda é uma divisão por 1 #
Phil
@ Phil, (0 == 0 || 0 % 1 == 0)irá avaliar a true.
tomekwi
Ah, a propósito 0 % 1 == 0também avalia a true! %não é divisão!
Novidade
13

Tenha cuidado ao usar

num% 1

string vazia ('') ou booleana (true ou false) retornará como número inteiro. Você pode não querer fazer isso

false % 1 // true
'' % 1 //true

Number.isInteger (dados)

Number.isInteger(22); //true
Number.isInteger(22.2); //false
Number.isInteger('22'); //false

função incorporada no navegador. Dosnt suporta navegadores antigos

Alternativas:

Math.round(num)=== num

No entanto, Math.round () também falhará para string vazia e booleana

Jhankar Mahbub
fonte
8

Para verificar se um número inteiro como o pôster deseja:

if (+data===parseInt(data)) {return true} else {return false}

observe + na frente dos dados (converte a string em número) e === para obter a exata.

Aqui estão alguns exemplos:

data=10
+data===parseInt(data)
true

data="10"
+data===parseInt(data)
true

data="10.2"
+data===parseInt(data)
false
user603749
fonte
6
Esta parece ser a solução mais inteligente para o meu caso (onde não me importo se é um número inteiro em uma string). No entanto: por que não apenas ir return (+data===parseInt(data))?
Swiss Mister
6
if(Number.isInteger(Number(data))){
    //-----
}
hóspede
fonte
11
Mesmo comentário abaixo: Não suportado pelo IE e Safari .
entrecruzamento
Agora, o @crisscross é suportado por tudo, exceto o IE, o que é apenas uma preocupação se você oferece suporte a sistemas operacionais legados.
Faintsignal
6

A solução pré-ECMAScript-6 mais simples e limpa (que também é suficientemente robusta para retornar false, mesmo que um valor não numérico, como uma string ou nulo, seja passado para a função) seria o seguinte:

function isInteger(x) { return (x^0) === x; } 

A solução a seguir também funcionaria, embora não seja tão elegante quanto a acima:

function isInteger(x) { return Math.round(x) === x; }

Observe que Math.ceil () ou Math.floor () pode ser usado igualmente bem (em vez de Math.round ()) na implementação acima.

Ou alternativamente:

function isInteger(x) { return (typeof x === 'number') && (x % 1 === 0); }

Uma solução incorreta bastante comum é a seguinte:

function isInteger(x) { return parseInt(x, 10) === x; }

Embora essa abordagem baseada em parseInt funcione bem para muitos valores de x, uma vez que x se torne bastante grande, ele não funcionará corretamente. O problema é que parseInt () restringe seu primeiro parâmetro a uma string antes de analisar dígitos. Portanto, uma vez que o número se torne suficientemente grande, sua representação em cadeia será apresentada na forma exponencial (por exemplo, 1e + 21). Consequentemente, parseInt () tentará analisar 1e + 21, mas interromperá a análise quando atingir o caractere e, portanto, retornará um valor de 1. Observe:

> String(1000000000000000000000)
'1e+21'

> parseInt(1000000000000000000000, 10)
1

> parseInt(1000000000000000000000, 10) === 1000000000000000000000
false
Arsen Aleksanyan
fonte
6

Por que ninguém mencionou Number.isInteger()?

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger

Funciona perfeitamente para mim e resolve o problema com o NaNnúmero inicial.

noites
fonte
11
Observe que este é o ES6, portanto, navegadores mais antigos (como o IE <= 11) não o suportam. Os documentos acima fornecem um polyfill.
bispo
Alguém fez menção Number.isInteger(), 3,5 anos antes: stackoverflow.com/a/27424770/5208540
Alex Stragies
se vamos para pegar um valor a partir de uma entrada seguida, verificar, Number.isInteger sempre retornará false como o valor de entrada é de tipo de dados seqüência
Shinigamae
6

No ES6, 2 novos métodos são adicionados ao Number Object.

Nele, o método Number.isInteger () retorna true se o argumento for um número inteiro.

Exemplo de uso:

Number.isInteger(10);        // returns true
Number.isInteger(10.5);      // returns false
Arun Joshla
fonte
4

O padrão ECMA-262 6.0 (ES6) inclui a função Number.isInteger .

Para adicionar suporte ao navegador antigo, recomendo o uso de uma solução forte e suportada pela comunidade em:

https://github.com/paulmillr/es6-shim

que é uma biblioteca pura de polyfills ES6 JS .

Note que esta lib requer es5-shim, basta seguir README.md.

gavenkoa
fonte
4

Você pode tentar Number.isInteger(Number(value))se valuepode ser um número inteiro na forma de sequência, por exemplo, var value = "23"e deseja que isso avalie true. Evite tentar, Number.isInteger(parseInt(value))porque isso nem sempre retorna o valor correto. por exemplo, se var value = "23abc"você usar a parseIntimplementação, ela ainda retornará verdadeira.

Mas se você deseja valores estritamente inteiros, provavelmente Number.isInteger(value)deve fazer o truque.

gbozee
fonte
11
Observe que isso não é suportado pelo IE; como afirmou aqui no docu eu tenho o meu scrip interrompido devido a isso, especialmente se o var que está a verificar é indefinido
mikewasmike
4
var x = 1.5;
if(!isNaN(x)){
 console.log('Number');
 if(x % 1 == 0){
   console.log('Integer');
 }
}else {
 console.log('not a number');
}
Hemant
fonte
3
Após 29 respostas, seria de esperar um pouco mais de explicações para tornar a sua resposta se destacam ...
brasofilo
3

Verifique se a variável é igual à mesma variável arredondada para um número inteiro, assim:

if(Math.round(data) != data) {
    alert("Variable is not an integer!");
}
Elliot Bonneville
fonte
Você pode muito facilmente corrigir edição deste função com o retorno truepara NaN, simplesmente mudando !=para !==e invertendo os ifblocos. Isso funciona porque NaNé o único valor em JavaScript que não se iguala. Por exemplo, o novo código deve serif (Math.round(x) === x) { /* x IS an integer! */ }
mgthomas99
3

Além disso Number.isInteger(),. Talvez Number.isSafeInteger()seja outra opção aqui , usando o especificado no ES6.

Para polyfill Number.isSafeInteger(..)em navegadores anteriores ao ES6:

Number.isSafeInteger = Number.isSafeInteger || function(num) {
    return typeof num === "number" && 
           isFinite(num) && 
           Math.floor(num) === num &&
           Math.abs( num ) <= Number.MAX_SAFE_INTEGER;
};
zangw
fonte
3

Number.isInteger() é a melhor maneira, se o seu navegador suportar, se não, acho que existem muitas maneiras de seguir:

function isInt1(value){
  return (value^0) === value
}

ou:

function isInt2(value){
  return (typeof value === 'number') && (value % 1 === 0); 
}

ou:

function isInt3(value){
  return parseInt(value, 10) === value; 
}

ou:

function isInt4(value){
  return Math.round(value) === value; 
}

agora podemos testar os resultados:

var value = 1
isInt1(value)   // return true
isInt2(value)   // return true
isInt3(value)   // return true
isInt4(value)   // return true

var value = 1.1
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

var value = 1000000000000000000
isInt1(value)   // return false
isInt2(value)   // return true
isInt3(value)   // return false
isInt4(value)   // return true

var value = undefined
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

var value = '1' //number as string
isInt1(value)   // return false
isInt2(value)   // return false
isInt3(value)   // return false
isInt4(value)   // return false

Portanto, todos esses métodos são funcionais, mas quando o número é muito grande, o parseInt e o operador ^ não funcionam bem.

Charles Chu
fonte
3

Apenas tente o seguinte:

let number = 5;
if (Number.isInteger(number)) {
    //do something
}
Jan WebDev
fonte
Number.isInteger () não é suportado em todas as versões dos navegadores IE.
SKR 20/02
2

Você poderia usar esta função:

function isInteger(value) {
    return (value == parseInt(value));
}

Ele retornará true, mesmo que o valor seja uma sequência que contenha um valor inteiro.
Portanto, os resultados serão:

alert(isInteger(1)); // true
alert(isInteger(1.2)); // false
alert(isInteger("1")); // true
alert(isInteger("1.2")); // false
alert(isInteger("abc")); // false
ferhrosa
fonte
2

Minha abordagem:

a >= 1e+21O teste só pode passar por um valor que precisa ser um número e um valor muito grande. Isso abrangerá todos os casos, com certeza, ao contrário de outras soluções fornecidas nesta discussão.

a === (a|0)Se o argumento da função fornecida for exatamente (===) o mesmo que o valor transformado em bits, significa que o argumento é um número inteiro.

a|0retornará 0para qualquer valor de aque não é um número , e se aé de fato um número, ele irá retirar afastado qualquer coisa depois do ponto decimal, por isso 1.0001vai se tornar1

function isInteger(a){
    return a >= 1e+21 ? true : a === (a|0)
}

/// tests ///////////////////////////
[
  1,                        // true
  1000000000000000000000,   // true
  4e2,                      // true
  Infinity,                 // true
  1.0,                      // true
  1.0000000000001,          // false
  0.1,                      // false
  "0",                      // false
  "1",                      // false
  "1.1",                    // false
  NaN,                      // false
  [],                       // false
  {},                       // false
  true,                     // false
  false,                    // false
  null,                     // false
  undefined                 // false
].forEach( a => console.log(typeof a, a, isInteger(a)) )

vsync
fonte
11
Boa ideia! Também gosto que você mostrou seus testes, mas infelizmente isso não considera um valor String de "0".
Jammer
Hey @vsync, não intencionalmente. Inicialmente, votei anteriormente, mas decidi revertê-lo novamente devido ao meu comentário anterior. Devo ter acidentalmente clicado duas vezes ou algo assim.
Jammer
1

Você pode usar o regexp para isso:

function isInteger(n) {
    return (typeof n == 'number' && /^-?\d+$/.test(n+''));
}
consternação
fonte
1

Use o |operador:

(5.3 | 0) === 5.3 // => false
(5.0 | 0) === 5.0 // => true

Portanto, uma função de teste pode ser assim:

var isInteger = function (value) {
  if (typeof value !== 'number') {
    return false;
  }

  if ((value | 0) !== value) {
    return false;
  }

  return true;
};
Golo Roden
fonte
1

Isso resolverá mais um cenário ( 121. ), um ponto no final

function isInt(value) {
        var ind = value.indexOf(".");
        if (ind > -1) { return false; }

        if (isNaN(value)) {
            return false;
        }

        var x = parseFloat(value);
        return (x | 0) === x;

    }
Muhammed Rafiq
fonte
1

Para valores inteiros positivos sem separadores:

return ( data !== '' && data === data.replace(/\D/, '') );

Testes 1. se não estiverem vazios e 2. se o valor for igual ao resultado da substituição de um caractere não dígito em seu valor.

DanielL
fonte
1

Ok, tenho menos, porque não descreveu meu exemplo, então mais exemplos :):

Eu uso expressão regular e método de teste:

var isInteger = /^[0-9]\d*$/;

isInteger.test(123); //true
isInteger.test('123'); // true
isInteger.test('sdf'); //false
isInteger.test('123sdf'); //false

// If u want to avoid string value:
typeof testVal !== 'string' && isInteger.test(testValue);
Vasyl Gutnyk
fonte
Obtido menos provavelmente porque o teste não é uma função.
imlokesh
@imlokesh, o que você quer dizer com "não é uma função"? oO eu escrevi eu uso "método de teste".
Vasyl Gutnyk
@imlokesh nenhum problema, eu só pedir U causa que eu usei na produção :) e eu pensei u encontrou algum bug :)
Vasyl Gutnyk
1

você também pode tentar dessa maneira

var data = 22;
if (Number.isInteger(data)) {
    console.log("integer");
 }else{
     console.log("not an integer");
 }

ou

if (data === parseInt(data, 10)){
    console.log("integer");
}else{
    console.log("not an integer");
}
Adeojo Emmanuel IMM
fonte
Isso produzirá o resultado errado para data=22.5;. Também os dois ramos têm console.log("not an integer"):: S
Colin Breame
0

Eu tive que verificar se uma variável (string ou número) é um número inteiro e usei esta condição:

function isInt(a){
    return !isNaN(a) && parseInt(a) == parseFloat(a);
}

http://jsfiddle.net/e267369d/1/

Algumas das outras respostas têm uma solução semelhante (confie na parseFloatcombinação com isNaN), mas a minha deve ser mais direta e autoexplicativa.


Edit: eu descobri que meu método falha para strings contendo vírgula (como "1,2") e também percebi que, no meu caso particular, quero que a função falhe se uma string não for um número inteiro válido (deve falhar em qualquer flutuação , mesmo 1.0). Então aqui está minha função Mk II:

function isInt(a){
    return !isNaN(a) && parseInt(a) == parseFloat(a) && (typeof a != 'string' || (a.indexOf('.') == -1 && a.indexOf(',') == -1));
}

http://jsfiddle.net/e267369d/3/

Obviamente, caso você realmente precise da função para aceitar números inteiros flutuantes (itens 1.0), você sempre poderá remover a condição de ponto a.indexOf('.') == -1.

jahu
fonte