Testando se um valor é ímpar ou par


173

Eu decidi criar simples eIgual e ISODD função com um algoritmo muito simples:

function isEven(n) {
  n = Number(n);
  return n === 0 || !!(n && !(n%2));
}

function isOdd(n) {
  return isEven(Number(n) + 1);
}

Tudo bem se n estiver com determinados parâmetros, mas falhar em muitos cenários. Então, decidi criar funções robustas que entregam resultados corretos para o maior número possível de cenários, para que apenas números inteiros dentro dos limites dos números javascript sejam testados, todo o resto retorne falso (incluindo + e - infinito). Observe que zero é par.

// Returns true if:
//
//    n is an integer that is evenly divisible by 2
//
// Zero (+/-0) is even
// Returns false if n is not an integer, not even or NaN
// Guard against empty string

(function (global) {

  function basicTests(n) {

    // Deal with empty string
    if (n === '') 
      return false;

    // Convert n to Number (may set to NaN)
    n = Number(n);

    // Deal with NaN
    if (isNaN(n)) 
      return false;

    // Deal with infinity - 
    if (n === Number.NEGATIVE_INFINITY || n === Number.POSITIVE_INFINITY)
      return false;

    // Return n as a number
    return n;
  }

  function isEven(n) {

    // Do basic tests
    if (basicTests(n) === false)
      return false;

    // Convert to Number and proceed
    n = Number(n);

    // Return true/false
    return n === 0 || !!(n && !(n%2));
  }
  global.isEven = isEven;

  // Returns true if n is an integer and (n+1) is even
  // Returns false if n is not an integer or (n+1) is not even
  // Empty string evaluates to zero so returns false (zero is even)
  function isOdd(n) {

    // Do basic tests
    if (basicTests(n) === false)
      return false;

    // Return true/false
    return n === 0 || !!(n && (n%2));
  }
  global.isOdd = isOdd;

}(this));

Alguém pode ver algum problema com o exposto acima? Existe uma versão melhor (ou seja, mais precisa, mais rápida ou mais concisa sem ser ofuscada)?

Existem várias postagens relacionadas a outros idiomas, mas não consigo encontrar uma versão definitiva para o ECMAScript.


Respostas:


368

Usar módulo:

function isEven(n) {
   return n % 2 == 0;
}

function isOdd(n) {
   return Math.abs(n % 2) == 1;
}

Você pode verificar se qualquer valor em Javascript pode ser coagido para um número com:

Number.isFinite(parseFloat(n))

Essa verificação deve ser feita preferencialmente fora das funções isEvene isOdd, para que você não precise duplicar o tratamento de erros nas duas funções.


@ Steve Sim, mas o JS tem alguns problemas especiais quando valuenão é um número, ou mesmo se for um número. Ex .: 0.1%2, NaN%2, []%2, etc. O que você escreveu na resposta, ele já sabe disso.
Alin Purcaru

1
0.1e NaNfuncione bem com a função acima. Array vazio é um pouco de dor, uma vez que equivale a 0 ...
Steve Mayne

4
@Lin - eu adicionei uma verificação numérica. Eu não estou certo que eu entender o cenário quando você iria querer uma função aritmética para lidar explicitamente outros tipos de dados, mas se é isso que o OP quer ...
Steve Mayne

2
Que tal mudar return n == parseInt(n);para return n === parseInt(n);?
JiminP

2
Acho que li em algum lugar o que você deve verificar n % 2 !== 0ao procurar números ímpares, porque não é necessariamente 1, dependendo do idioma. EDIT: Ah, é para isso que .absserve. Deixa pra lá então.
ptf

78

Eu prefiro usar um pouco de teste:

if(i & 1)
{
    // ODD
}
else
{
    // EVEN
}

Isso testa se o primeiro bit está no qual significa um número ímpar.


Útil apenas se você souber que eu sou um número para começar. Os não números devem retornar indefinidos (ou talvez gerar um erro, mas indefinidos parece sensato).
`` #

3
Absolutamente. Usando o módulo de base 2 matemática deve ser ilegal;)
aceofspades

4
Ternário: i & 1 == 1 ? console.log("odd") : console.log("even");Além disso, uma eficiência de nível de bits (não tão amplamente utilizado em JS)
Jacksonkr

13
@Jacksonkr Observe que não há "eficiência no nível de bits" no JavaScript, porque todos os números são flutuantes no JavaScript e usar um operador bit a bit significa primeiro convertê-lo em um int, depois executar a operação e depois convertê-lo novamente em um número de ponto flutuante.
poke

1
@poke Correto, eles são do tipo Number, mas é bom saber que há eficiência em idiomas com tipos fortes.
Robert Brisita

8

Que tal o seguinte? Eu só testei isso no IE, mas fiquei muito feliz ao lidar com cadeias de caracteres que representam números de qualquer tamanho, números reais que eram números inteiros ou flutuantes e as duas funções retornaram false quando passadas por um booleano, indefinido, nulo, uma matriz ou um objeto. (Você decide ignorar os espaços em branco à esquerda ou à direita quando uma string é passada - presumi que eles não sejam ignorados e façam com que ambas as funções retornem falsas.)

function isEven(n) {
   return /^-?\d*[02468]$/.test(n);
}

function isOdd(n) {
   return /^-?\d*[13579]$/.test(n);
}

2
Para minha implementação, isEven (2.122e3) retorna true, mas isEven ("2.122e3") retorna false. Por outro lado, meu isEven () falha em números realmente grandes, porque JS os coloca no formato de expoente ao converter em sequência para o teste de expressão regular. Ah bem.
Nnnnnn

@ MartijnScheffer - Sinta-se à vontade para me enviar a conta de toda a memória extra que você terá que comprar. Observe que a pergunta incluiu conversões de outros tipos para número, e claramente o que estou sugerindo aqui é ter uma função simples de uma linha que lida com números e seqüências de caracteres. Obviamente, de acordo com meu próprio comentário, isso realmente não trata de todos os casos possíveis, mas ainda pode ser útil - regex é a maneira mais simples de validar dados inseridos pelo usuário, que será uma string inicialmente.
Nnnnnn

eu postei um comentário aqui? não o vejo, mas posso, se você quiser um !, essa NÃO é uma solução correta, é centenas de vezes mais lenta e estamos falando de números, não de strings, se você quiser verificar se uma string é válida número e um número inteiro que pode ser tratado separadamente.
Martijn Scheffer

@MartijnScheffer - Sim, houve um comentário seu, parece ter sido excluído em algum momento desde a minha resposta. Observe que a pergunta não era apenas sobre números, o código do OP incluía conversões de outros tipos. De qualquer forma, obrigado pelo seu feedback.
nnnnnn 10/01

7

Nota: também existem números negativos.

function isOddInteger(n)
{
   return isInteger(n) && (n % 2 !== 0);
}

Onde

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

1
Analise não precisa de uma raiz aqui?
precisa

@blablabla Sim, nem todas as implementações assumir radix = 10.
Rodrigo

Boa citação de valores negativos. A resposta de Robert Brisita (que foi adicionada mais tarde) também cobre isso.
Jacksonkr

4

Por que não fazer isso:

    function oddOrEven(num){
        if(num % 2 == 0)
            return "even";
        return "odd";
    }
    oddOrEven(num);

Ou mesmo function isEven(num) { return num % 2 == 0}
chiapa 14/09

3
ou com ES6:const oddOrEven = num => num % 2 === 0 ? 'even' : 'odd'
enguerran

4

Para concluir o teste de bits de Robert Brisita.

if ( ~i & 1 ) {
    // Even
}

1
var isEven = function(number) {
    // Your code goes here!
    if (number % 2 == 0){
       return(true);
    }
    else{
       return(false);    
    }
};

2
O if ( <expression> ) return true else return falseparadigma sempre pode ser simplificado para return ( <expression> )(já que a expressão em um if já é sempre booleana).
Gerold Broser

dizendo que o retorno não é uma função, é como dizer se não é uma função, é perfeitamente válido usar parênteses ao retornar um valor (mesmo que eles não são não é útil aqui)
Martijn Scheffer

1

Uma simples modificação / melhoria da resposta de Steve Mayne!

function isEvenOrOdd(n){
    if(n === parseFloat(n)){
        return isNumber(n) && (n % 2 == 0);
    }
    return false;
}

Nota: Retorna false se inválido!


1

Só precisamos de uma linha de código para isso!

Aqui está uma maneira mais nova e alternativa de fazer isso, usando a nova sintaxe ES6 para funções JS e a sintaxe de uma linha da if-elsechamada de instrução:

const isEven = num => ((num % 2) == 0) ? true : false;

alert(isEven(8));  //true
alert(isEven(9));  //false
alert(isEven(-8)); //true

1
Qual é mais curto que let isEven = num => num % 2 === 0. :-) Mas realmente não é diferente de muitas outras respostas aqui.
RobG

1

Um pouco

x % 2 == 0; // Check if even

!(x & 1); // bitmask the value with 1 then invert.

((x >> 1) << 1) == x; // divide value by 2 then multiply again and check against original value

~x&1; // flip the bits and bitmask

0

Maneira diferente:

var isEven = function(number) {
  // Your code goes here!
  if (((number/2) - Math.floor(number/2)) === 0) {return true;} else {return false;};
};

isEven(69)

0

Caso contrário, usando seqüências de caracteres, porque por que não

function isEven(__num){
    return String(__num/2).indexOf('.') === -1;
}

0
if (testNum == 0);
else if (testNum % 2  == 0);
else if ((testNum % 2) != 0 );

Sem explicação, sua contribuição não tem muito valor. Também repete as informações que já foram apresentadas na discussão.
Cindy Meister

Obrigado Cindy! Apenas oferecendo uma solução!
27416 Lindsay

Mas ... isso realmente não faz nada. Não deveria retornar algo?
Nnnnnn 13/10

0

Talvez isto? if (ourNumber% 2! == 0)


2
Embora esse trecho de código possa resolver a questão, incluir uma explicação realmente ajuda a melhorar a qualidade da sua postagem. Lembre-se de que você está respondendo à pergunta dos leitores no futuro e essas pessoas podem não saber os motivos da sua sugestão de código. Tente também não sobrecarregar seu código com comentários explicativos, pois isso reduz a legibilidade do código e das explicações!
Filnor

0
var num = someNumber
    isEven;
parseInt(num/2) === num/2 ? isEven = true : isEven = false;

0

for(var a=0; a<=20;a++){
   if(a%2!==0){
       console.log("Odd number "+a);
   }
}

for(var b=0; b<=20;a++){
    if(b%2===0){
        console.log("Even number "+b);  
    }     
 }


Embora esse código possa resolver a questão, incluir uma explicação de como e por que isso resolve o problema realmente ajudaria a melhorar a qualidade da sua postagem e provavelmente resultaria em mais votos positivos. Lembre-se de que você está respondendo à pergunta dos leitores no futuro, não apenas à pessoa que está perguntando agora. Por favor edite sua resposta para adicionar explicações e dar uma indicação do que limitações e premissas se aplicam.
Daniil

-1

Para testar se você tem ou não um número par ou ímpar, isso também funciona.

const comapare = x => integer(checkNumber(x));

function checkNumber (x) {
   if (x % 2 == 0) {
       return true;
   } 
   else if (x % 2 != 0) {
       return false;
    }
}

function integer (x) {
   if (x) {
       console.log('even');
   } 
   else {
       console.log('odd');
    }
}

-1

Usando o estilo javascript moderno:

const NUMBERS = "nul one two three four five six seven ocho nueve".split(" ")

const isOdd  = n=> NUMBERS[n % 10].indexOf("e")!=-1
const isEven = n=> isOdd(+n+1)

isOdd('5'))retorna verdadeiro. isEven('5')também retorna verdadeiro. isOdd(NaN)gera um erro. :-(
RobG

Fixed isEven('5'). isOdd(NaN)provavelmente deve lançar um erro.
gunn

1
O host do script não deve estar lidando com o erro, a função deve. Sempre me disseram que um dump principal não é um término normal . ;-)
RobG

-2

Este é mais simples!

  var num = 3 //instead get your value here
  var aa = ["Even", "Odd"];

  alert(aa[num % 2]);

1
Isso retornará indefinido paranum = -1
Linus Oleander

-2
function isEven(n) {return parseInt(n)%2===0?true:parseInt(n)===0?true:false}

quando 0 / até queria, mas

isEven(0) //true
isEven(1) //false
isEven(2) //true
isEven(142856) //true
isEven(142856.142857)//true
isEven(142857.1457)//false

O que outras pessoas estão dizendo


Or return parseInt(n)%2===0?true:parseInt(n)===0. mas, novamente, isso é o mesmo que muitas das outras respostas já aqui.
Heretic Monkey

1
Or return parseInt(n)%2 === 0 || parseInt(n) === 0. Mas por que analisar ? Isso retorna verdadeiro para valores como "32foo" e 12.5, que não são pares.
RobG 5/06/19

-2
if (i % 2) {
return odd numbers
}

if (i % 2 - 1) {
return even numbers
}

1
quando será o lembrete de dividir qualquer número por 2?
User85421

Sim, você tem razão. Sinto falta de escrever% 2 == 2. Meu mal.
Dejan Markovic
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.