Tester si une valeur est paire ou impaire


173

J'ai décidé de créer des fonctions isEven et isOdd simples avec un algorithme très simple:

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

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

C'est OK si n est avec certains paramètres, mais échoue dans de nombreux scénarios. J'ai donc entrepris de créer des fonctions robustes qui fournissent des résultats corrects pour autant de scénarios que possible, de sorte que seuls les entiers dans les limites des nombres javascript soient testés, tout le reste retourne faux (y compris + et - infini). Notez que zéro est pair.

// 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));

Quelqu'un peut-il voir des problèmes avec ce qui précède? Existe-t-il une version meilleure (c'est-à-dire plus précise, plus rapide ou plus concise sans être obscurcie)?

Il existe divers articles relatifs à d'autres langues, mais je n'arrive pas à trouver une version définitive pour ECMAScript.


Réponses:


368

Utiliser le module:

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

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

Vous pouvez vérifier que toute valeur en Javascript peut être forcée à un nombre avec:

Number.isFinite(parseFloat(n))

Cette vérification doit de préférence être effectuée en dehors des fonctions isEvenet isOdd, pour ne pas avoir à dupliquer la gestion des erreurs dans les deux fonctions.


@Steve Oui, mais JS a des problèmes particuliers quand ce valuen'est pas un nombre, ou même si c'est un nombre. Ex .: 0.1%2, NaN%2, []%2, etc. Qu'est - ce que vous avez écrit dans la réponse, il sait déjà.
Alin Purcaru

1
0.1et NaNfonctionne correctement avec la fonction ci-dessus. Un tableau vide est un peu pénible car il équivaut à 0 ...
Steve Mayne

4
@Alin - J'ai ajouté une vérification numérique. Je ne suis pas sûr de comprendre le scénario où vous voudriez qu'une fonction arithmétique gère explicitement d'autres types de données, mais si c'est ce que veut l'OP ...
Steve Mayne

2
Qu'en est- il changer return n == parseInt(n);pour return n === parseInt(n);?
JiminP

2
Je pense avoir lu quelque part ce que vous devriez vérifier n % 2 !== 0lors de la vérification des nombres impairs, car ce n'est pas nécessairement 1, selon la langue. EDIT: Ah, c'est ce que l' .absappel est pour. Pas de soucis alors.
ptf

80

Je préfère utiliser un petit test:

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

Cela teste si le premier bit est sur lequel signifie un nombre impair.


Seulement utile si vous savez que je suis un nombre pour commencer. Les non-nombres devraient renvoyer undefined (ou peut-être lancer une erreur, mais undefined semble raisonnable).
RobG

3
Absolument. L'utilisation du module pour les mathématiques de base 2 devrait être illégale;)
aceofspades

4
Ternaire: i & 1 == 1 ? console.log("odd") : console.log("even");Aussi, +1 pour l'efficacité au niveau du bit (pas aussi largement utilisé dans JS)
Jacksonkr

13
@Jacksonkr Notez qu'il n'y a pas d '«efficacité au niveau du bit» en JavaScript car tous les nombres sont flottants en JavaScript et l'utilisation d'un opérateur au niveau du bit signifie d'abord le convertir en un entier, puis effectuer l'opération, puis le reconvertir en un nombre à virgule flottante.
poke le

1
@poke Correct, ils sont de type Number mais il est bon de savoir qu'il y a de l'efficacité dans les langages fortement typés.
Robert Brisita le

8

Que diriez-vous de ce qui suit? Je n'ai testé cela que dans IE, mais c'était assez heureux de gérer des chaînes représentant des nombres de n'importe quelle longueur, des nombres réels qui étaient des entiers ou des flottants, et les deux fonctions renvoyaient false lorsqu'elles étaient passées un booléen, undefined, null, un tableau ou un objet. (À vous de décider si vous voulez ignorer les blancs de début ou de fin lorsqu'une chaîne est passée - j'ai supposé qu'ils ne sont pas ignorés et que les deux fonctions retournent false.)

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

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

2
Pour mon implémentation, isEven (2.122e3) renvoie true, mais isEven ("2.122e3") renvoie false. Inversement, mon isEven () échoue pour de très gros nombres car JS les met au format exposant lors de la conversion en chaîne pour le test regex. Tant pis.
nnnnnn

@MartijnScheffer - N'hésitez pas à m'envoyer la facture de toute cette mémoire supplémentaire que vous aurez à acheter. Notez que la question incluait des conversions d'autres types en nombre, et clairement le but de ce que je suggère ici est d'avoir une fonction simple sur une ligne qui gère les nombres et les chaînes. Bien sûr, selon mon propre commentaire, cela ne gère pas tous les cas possibles, mais cela peut quand même être utile - regex est le moyen le plus simple de valider les données entrées par l'utilisateur, qui seront initialement une chaîne.
nnnnnn

ai-je publié un commentaire ici? je ne le vois pas, mais je peux si vous en voulez un!, ce n'est PAS une solution correcte, c'est des centaines de fois plus lent, et nous parlons de nombres et non de chaînes, si vous voulez vérifier si une chaîne est valide number, et un entier qui peut être traité séparément.
Martijn Scheffer

@MartijnScheffer - Oui, il y a eu un commentaire de votre part, semble avoir été supprimé à un moment donné depuis ma réponse. Notez que la question n'était pas seulement sur les nombres, le code de l'OP incluait des conversions d'autres types. Quoi qu'il en soit, merci pour vos commentaires.
nnnnnn

7

Remarque: il existe également des nombres négatifs.

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

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

1
ParseInt n'a-t-il pas besoin d'un radix ici?
blablabla

@blablabla Oui, toutes les implémentations ne supposent pas que radix = 10.
Rodrigo

Bonne citation des valeurs négatives. La réponse de Robert Brisita (qui a été ajoutée plus tard) couvre également cela.
Jacksonkr

4

Pourquoi ne pas simplement faire ceci:

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

Ou même function isEven(num) { return num % 2 == 0}
chiapa

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


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

2
Le if ( <expression> ) return true else return falseparadigme peut toujours être simplifié en return ( <expression> )(puisque l'expression dans un if déjà est toujours booléenne).
Gerold Broser

dire que le retour n'est pas une fonction, c'est comme dire si ce n'est pas une fonction, il est parfaitement valide d'utiliser des parenthèses lors du retour d'une valeur (même si elles ne sont pas utiles ici)
Martijn Scheffer

1

Une simple modification / amélioration de la réponse de Steve Mayne!

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

Remarque: renvoie false si non valide!


1

Nous avons juste besoin d'une ligne de code pour cela!

Voici une façon plus nouvelle et alternative de le faire, en utilisant la nouvelle syntaxe ES6 pour les fonctions JS et la syntaxe sur une ligne pour l' if-elseappel d'instruction:

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

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

1
Ce qui est plus court que let isEven = num => num % 2 === 0. :-) Mais vraiment ce n'est pas différent de beaucoup d'autres réponses ici.
RobG

1

Quelques

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

Autrement:

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

isEven(69)

0

Sinon, utiliser des chaînes car pourquoi pas

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

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

Sans aucune explication, votre contribution n'a pas beaucoup de valeur. Il reprend également les informations déjà présentées lors de la discussion.
Cindy Meister

Merci Cindy! Offrir simplement une solution!
Lindsay

Mais ... cela ne fait pas faire quoi que ce soit. Ne devrait-il pas retourner quelque chose?
nnnnnn

0

Peut être ça? if (notreNombre% 2! == 0)


2
Bien que cet extrait de code puisse résoudre la question, inclure une explication contribue vraiment à améliorer la qualité de votre message. N'oubliez pas que vous répondez à la question aux lecteurs à l'avenir, et que ces personnes pourraient ne pas connaître les raisons de votre suggestion de code. Essayez également de ne pas surcharger votre code avec des commentaires explicatifs, cela réduit la lisibilité du code et des explications!
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);  
    }     
 }


Bien que ce code puisse résoudre la question, inclure une explication sur comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre publication et entraînerait probablement plus de votes à la hausse. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limites et des hypothèses applicables.
Daniil le

-1

Pour tester si vous avez un nombre pair ou impair, cela fonctionne également.

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

Utilisation du style javascript moderne:

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'))renvoie vrai. isEven('5')renvoie également vrai. isOdd(NaN)jette une erreur. :-(
RobG

Fixe isEven('5'). isOdd(NaN)devrait probablement lancer une erreur.
gunn

1
L'hôte du script ne doit pas gérer l'erreur, la fonction doit le faire. On m'a toujours dit qu'un vidage de mémoire n'était pas une terminaison normale . ;-)
RobG

-2

Celui-ci est plus simple!

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

  alert(aa[num % 2]);

1
Cela reviendra indéfini pournum = -1
Linus Oleander

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

quand 0 / même voulu mais

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


Ou return parseInt(n)%2===0?true:parseInt(n)===0. mais là encore, c'est la même chose que la plupart des autres réponses déjà ici.
Heretic Monkey

1
Ou return parseInt(n)%2 === 0 || parseInt(n) === 0. Mais pourquoi parseInt ? Cela renvoie vrai pour les valeurs comme "32foo" et 12.5, qui ne sont pas paires.
RobG

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

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

1
Quand le rappel de diviser un nombre par 2 sera-t-il 2?
user85421

Hm, oui vous avez raison. Je m'ennuie d'écrire% 2 == 2. Mon mauvais.
Dejan Markovic
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.