Probar si un valor es par o impar

173

Decidí crear funciones simples isEven e isOdd con un algoritmo muy simple:

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

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

Eso está bien si n está con ciertos parámetros, pero falla en muchos escenarios. Así que me propuse crear funciones robustas que brinden resultados correctos para tantos escenarios como pueda, de modo que solo se prueben los enteros dentro de los límites de los números de JavaScript, todo lo demás devuelve falso (incluido + e - infinito). Tenga en cuenta que cero es 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));

¿Alguien puede ver algún problema con lo anterior? ¿Existe una versión mejor (es decir, más precisa, más rápida o más concisa sin ofuscarse)?

Hay varias publicaciones relacionadas con otros idiomas, pero parece que no puedo encontrar una versión definitiva para ECMAScript.

RobG
fuente

Respuestas:

368

Usar módulo:

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

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

Puede verificar que cualquier valor en Javascript se puede convertir a un número con:

Number.isFinite(parseFloat(n))

Esta verificación debe realizarse preferiblemente fuera de las funciones isEveny isOdd, para que no tenga que duplicar el manejo de errores en ambas funciones.

Steve Mayne
fuente
@Steve Sí, pero JS tiene algunos problemas especiales cuando valueno es un número, o incluso si es un número. Ej .: 0.1%2, NaN%2, []%2, etc. Lo que escribió en la respuesta, ya lo sabe.
Alin Purcaru
1
0.1y NaNfunciona bien con la función anterior. La matriz vacía es un poco molesta ya que equivale a 0 ...
Steve Mayne
44
@Alin: agregué un control numérico. No estoy seguro de entender el escenario cuando desea una función aritmética para manejar explícitamente otros tipos de datos, pero si eso es lo que quiere el OP ...
Steve Mayne
2
¿Qué hay de cambiar return n == parseInt(n);a return n === parseInt(n);?
JiminP
2
Creo que leí en alguna parte lo que debe verificar n % 2 !== 0al verificar números impares, porque no es necesariamente 1, dependiendo del idioma. EDITAR: Ah, para eso está la .absllamada. Olvidalo entonces.
ptf
78

Prefiero usar una prueba de bit:

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

Esto prueba si el primer bit está activado, lo que significa un número impar.

Robert Brisita
fuente
Sólo es útil si se sabe que es un número para empezar. Los no números deben devolver indefinidos (o tal vez arrojar un error, pero indefinido parece razonable)
RobG
3
Absolutamente. Usar módulo para matemática de base 2 debería ser ilegal;)
aceofspades
44
Ternario: i & 1 == 1 ? console.log("odd") : console.log("even");Además, +1 para la eficiencia del nivel de bits (no tan utilizado en JS)
Jacksonkr
13
@Jacksonkr Tenga en cuenta que no hay "eficiencia de nivel de bit" en JavaScript porque todos los números son flotantes en JavaScript y usar un operador bit a bit significa primero convertirlo en int, luego realizar la operación y luego convertirlo de nuevo a un número de coma flotante.
meter
1
@poke Correct son de tipo Number pero es bueno saber que hay eficiencia en los idiomas fuertemente tipados.
Robert Brisita
8

¿Qué tal lo siguiente? Solo probé esto en IE, pero estaba muy contento de manejar cadenas que representan números de cualquier longitud, números reales que eran enteros o flotantes, y ambas funciones devuelven falso cuando se pasa un booleano, indefinido, nulo, una matriz o un objeto. (Depende de usted si desea ignorar los espacios en blanco iniciales o finales cuando se pasa una cadena; he asumido que no se ignoran y hacen que ambas funciones devuelvan falso).

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

function isOdd(n) {
   return /^-?\d*[13579]$/.test(n);
}
nnnnnn
fuente
2
Para mi implementación, isEven (2.122e3) devuelve verdadero, pero isEven ("2.122e3") devuelve falso. Por el contrario, mi isEven () falla para números realmente grandes porque JS los pone en el formato de exponente cuando se convierte en cadena para la prueba de expresiones regulares. Oh bien.
nnnnnn
@MartijnScheffer: no dude en enviarme la factura por toda esa memoria adicional que tendrá que comprar. Tenga en cuenta que la pregunta sí incluyó conversiones de otros tipos a números, y claramente el punto de lo que sugiero aquí es tener una función simple de una línea que maneje números y cadenas. Por supuesto, según mi propio comentario, esto en realidad no maneja todos los casos posibles, pero aún puede ser útil: la expresión regular es la forma más simple de validar los datos ingresados ​​por el usuario, que inicialmente serán una cadena.
nnnnnn
¿publiqué un comentario aquí? ¡No lo veo, pero puedo si quieres una !, esta NO es una solución correcta, esta es cientos de veces más lenta, y estamos hablando de números, no cadenas, si quieres verificar si una cadena es válida número y un número entero que se puede manejar por separado.
Martijn Scheffer
@MartijnScheffer - Sí, hubo un comentario tuyo, parece que se ha eliminado en algún momento desde mi respuesta. Tenga en cuenta que la pregunta no era solo sobre números, el código del OP incluía conversiones de otros tipos. De todos modos, gracias por sus comentarios.
nnnnnn
7

Nota: también hay números negativos.

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

dónde

function isInteger(n)
{
   return n === parseInt(n, 10);
}
Ivo Renkema
fuente
1
¿No necesita una raíz aquí?
blablabla
@blablabla Sí, no todas las implementaciones suponen radix = 10.
Rodrigo
Buena cita de valores negativos. La respuesta de Robert Brisita (que se agregó más adelante) también cubre esto.
Jacksonkr
4

¿Por qué no solo hacer esto?

    function oddOrEven(num){
        if(num % 2 == 0)
            return "even";
        return "odd";
    }
    oddOrEven(num);
cifrar
fuente
O incluso function isEven(num) { return num % 2 == 0}
chiapa
3
o con ES6:const oddOrEven = num => num % 2 === 0 ? 'even' : 'odd'
enguerran el
4

Para completar la prueba de bits de Robert Brisita.

if ( ~i & 1 ) {
    // Even
}
Raoul Kieffer
fuente
1
var isEven = function(number) {
    // Your code goes here!
    if (number % 2 == 0){
       return(true);
    }
    else{
       return(false);    
    }
};
Pandemia
fuente
2
El if ( <expression> ) return true else return falseparadigma siempre se puede simplificar a return ( <expression> )(ya que la expresión en un if ya es siempre booleana).
Gerold Broser
decir que return no es una función, es como decir que si no es una función, es perfectamente válido usar paréntesis al devolver un valor (incluso si no son útiles aquí)
Martijn Scheffer
1

¡Una simple modificación / mejora de la respuesta de Steve Mayne!

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

Nota: ¡Devuelve falso si no es válido!

Eduardo Lucio
fuente
1

¡Solo necesitamos una línea de código para esto!

Aquí hay una forma más nueva y alternativa de hacer esto, utilizando la nueva sintaxis ES6 para las funciones JS y la sintaxis de una línea para la if-elsellamada a la instrucción:

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

alert(isEven(8));  //true
alert(isEven(9));  //false
alert(isEven(-8)); //true
Fellipe Sanches
fuente
1
Que es más corto como let isEven = num => num % 2 === 0. :-) Pero realmente no es diferente a muchas otras respuestas aquí.
RobG
1

Unos pocos

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
Vacío
fuente
0

Diferente modo:

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

isEven(69)
grizmin
fuente
0

De lo contrario, usar cadenas porque ¿por qué no?

function isEven(__num){
    return String(__num/2).indexOf('.') === -1;
}
Eric
fuente
0
if (testNum == 0);
else if (testNum % 2  == 0);
else if ((testNum % 2) != 0 );
Lindsay
fuente
Sin explicación, su contribución no tiene mucho valor. También repite información que ya se ha presentado en la discusión.
Cindy Meister el
Gracias Cindy! ¡Solo estoy ofreciendo una solución!
Lindsay
Pero ... esto en realidad no hace nada. ¿No debería devolver algo?
nnnnnn
0

¿Tal vez esto? if (ourNumber% 2! == 0)

gavr1loo
fuente
2
Si bien este fragmento de código puede resolver la pregunta, incluir una explicación realmente ayuda a mejorar la calidad de su publicación. Recuerde que está respondiendo la pregunta para los lectores en el futuro, y que esas personas podrían no conocer los motivos de su sugerencia de código. Por favor, también trate de no saturar su código con comentarios explicativos, ¡esto reduce la legibilidad tanto del código como de las explicaciones!
Filnor
0
var num = someNumber
    isEven;
parseInt(num/2) === num/2 ? isEven = true : isEven = false;
Nelles
fuente
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);  
    }     
 }

Hamza Ali
fuente
Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación, y probablemente resultaría en más votos positivos. Recuerde que está respondiendo la pregunta para los lectores en el futuro, no solo la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Daniil
-1

Para probar si tiene o no un número par o impar, esto también 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');
    }
}
Siop
fuente
-1

Usando 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)
Gunn
fuente
isOdd('5'))devuelve verdadero isEven('5')También devuelve verdadero. isOdd(NaN)arroja un error :-(
RobG
Fijo isEven('5'). isOdd(NaN)Probablemente debería arrojar un error.
gunn
1
El host de script no debería manejar el error, la función debería. Siempre me dijeron que un volcado del núcleo no es una terminación normal . ;-)
RobG
-2

¡Este es más simple!

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

  alert(aa[num % 2]);
AndroidManifester
fuente
1
Eso volverá indefinido paranum = -1
Linus Oleander
-2
function isEven(n) {return parseInt(n)%2===0?true:parseInt(n)===0?true:false}

cuando 0 / incluso quería pero

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

chris188
fuente
O return parseInt(n)%2===0?true:parseInt(n)===0. pero, de nuevo, esto es lo mismo que muchas de las otras respuestas que ya están aquí.
Heretic Monkey
1
O return parseInt(n)%2 === 0 || parseInt(n) === 0. ¿Pero por qué analizar ? Eso devuelve verdadero para valores como "32foo" y 12.5, que no son pares.
RobG
-2
if (i % 2) {
return odd numbers
}

if (i % 2 - 1) {
return even numbers
}
Dejan Markovic
fuente
1
¿Cuándo será 2 el recordatorio de dividir cualquier número entre 2?
user85421
Hm, sí, tienes razón. Echo de menos escribir% 2 == 2. Mi mal.
Dejan Markovic