Verifica se un valore è pari o dispari


173

Ho deciso di creare la semplice funzione isEven e isOdd con un algoritmo molto semplice:

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

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

Questo è OK se n è con alcuni parametri, ma fallisce per molti scenari. Quindi ho deciso di creare funzioni robuste che offrano risultati corretti per tutti gli scenari che ho potuto, in modo che vengano testati solo numeri interi entro i limiti dei numeri javascript, tutto il resto restituisce false (inclusi + e - infinito). Si noti che zero è pari.

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

Qualcuno può vedere problemi con quanto sopra? Esiste una versione migliore (ovvero più accurata, più veloce o più concisa senza essere offuscata)?

Esistono vari post relativi ad altre lingue, ma non riesco a trovare una versione definitiva per ECMAScript.


Risposte:


368

Usa il modulo:

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

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

Puoi verificare che qualsiasi valore in Javascript possa essere forzato su un numero con:

Number.isFinite(parseFloat(n))

Questo controllo dovrebbe preferibilmente essere eseguito al di fuori delle funzioni isEvene isOdd, quindi non è necessario duplicare la gestione degli errori in entrambe le funzioni.


@Steve Sì, ma JS ha alcuni problemi speciali quando valuenon è un numero o anche se è un numero. Es .: 0.1%2, NaN%2, []%2, ecc Quello che hai scritto nella risposta, lui già lo sa.
Alin Purcaru,

1
0.1e NaNfunziona bene con la funzione sopra. L'array vuoto è un po 'doloroso in quanto equivale a 0 ...
Steve Mayne,

4
@Alin - Ho aggiunto un controllo numerico. Non sono sicuro di capire lo scenario in cui vorresti che una funzione aritmetica gestisse esplicitamente altri tipi di dati, ma se è quello che vuole l'OP ...
Steve Mayne,

2
Che ne dici di passare return n == parseInt(n);a return n === parseInt(n);?
JiminP

2
Penso di aver letto da qualche parte cosa dovresti controllare n % 2 !== 0quando controlli i numeri dispari, perché non è necessariamente 1, a seconda della lingua. EDIT: Ah, questo è ciò che serve per la .abschiamata. Allora non importa.
ptf,

79

Preferisco usare un bit test:

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

In questo modo viene verificato se il primo bit è attivo per indicare un numero dispari.


Utile solo se si conoscono i è un numero di partenza. I non numeri dovrebbero restituire indefiniti (o forse generare un errore, ma indefiniti sembrano sensati).
RobG

3
Assolutamente. L'uso del modulo per la matematica di base 2 dovrebbe essere illegale;)
aceofspades il

4
Ternario: i & 1 == 1 ? console.log("odd") : console.log("even");Inoltre, +1 per l'efficienza a livello di bit (non così ampiamente utilizzato in JS)
Jacksonkr

13
@Jacksonkr Nota che non esiste "efficienza a livello di bit" in JavaScript perché tutti i numeri sono float in JavaScript e l'utilizzo di un operatore bit a bit significa prima convertirlo in un int, quindi eseguire l'operazione e quindi riconvertirlo in un numero in virgola mobile.
colpì il

1
@poke Corretti sono di tipo Numero ma è bello sapere che c'è efficienza nei linguaggi fortemente tipizzati.
Robert Brisita,

8

Che ne dici di quanto segue? L'ho provato solo in IE, ma era abbastanza felice di gestire stringhe che rappresentavano numeri di qualsiasi lunghezza, numeri reali che erano numeri interi o float ed entrambe le funzioni restituivano false quando veniva passato un valore booleano, indefinito, null, un array o un oggetto. (A te se vuoi ignorare gli spazi vuoti iniziali o finali quando viene passata una stringa - ho assunto che non vengano ignorati e che entrambe le funzioni restituiscano false.)

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

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

2
Per la mia implementazione isEven (2.122e3) restituisce true, ma isEven ("2.122e3") restituisce false. Al contrario, il mio isEven () fallisce per numeri veramente grandi perché JS li mette nel formato esponente durante la conversione in stringa per il test regex. Oh bene.
nnnnnn,

@MartijnScheffer - Sentiti libero di inviarmi il conto per tutta quella memoria aggiuntiva che dovrai acquistare. Si noti che la domanda includeva conversioni da altri tipi a numero e chiaramente il punto di ciò che sto suggerendo qui è avere una semplice funzione a una riga che gestisca numeri e stringhe. Ovviamente, secondo il mio commento, questo in realtà non gestisce tutti i casi possibili, ma può ancora essere utile - regex è il modo più semplice per convalidare i dati inseriti dall'utente, che inizialmente sarà una stringa.
nnnnnn,

ho pubblicato un commento qui? non lo vedo, ma posso farlo se ne vuoi uno!, NON è una soluzione corretta, è centinaia di volte più lento e stiamo parlando di numeri e non di stringhe, se vuoi verificare se una stringa è valida numero e un numero intero che può essere gestito separatamente.
Martijn Scheffer il

@MartijnScheffer - Sì, c'è stato un tuo commento, sembra essere stato cancellato ad un certo punto dalla mia risposta. Si noti che la domanda non riguardava solo i numeri, il codice del PO includeva conversioni di altri tipi. Comunque, grazie per il tuo feedback.
nnnnnn,

7

Nota: ci sono anche numeri negativi.

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

dove

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

1
Non ha bisogno di un'analisi qui?
blablabla,

@blablabla Sì, non tutte le implementazioni assumono radix = 10.
Rodrigo il

Buona citazione di valori negativi. La risposta di Robert Brisita (che è stata aggiunta in seguito) copre anche questo.
Jacksonkr,

4

Perché non fare solo questo:

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

O anche function isEven(num) { return num % 2 == 0}
Chiapa,

3
o con 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
Il if ( <expression> ) return true else return falseparadigma può sempre essere semplificato return ( <expression> )(poiché l'espressione in un if già è sempre booleana).
Gerold Broser,

dire che return non è una funzione, è come dire se non è una funzione, è perfettamente valido usare la parentesi quando si restituisce un valore (anche se qui non sono utili)
Martijn Scheffer

1

Una semplice modifica / miglioramento della risposta di Steve Mayne!

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

Nota: restituisce false se non valido!


1

Abbiamo solo bisogno di una riga di codice per questo!

Ecco un modo più nuovo e alternativo per farlo, usando la nuova sintassi ES6 per le funzioni JS e la sintassi a una riga per la if-elsechiamata dell'istruzione:

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

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

1
Che è più corto di let isEven = num => num % 2 === 0. :-) Ma davvero non è diverso da molte altre risposte qui.
RobG

1

Alcune

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

Un modo differente:

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

isEven(69)

0

Altrimenti usa le stringhe perché perché no

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

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

Senza alcuna spiegazione il tuo contributo non ha molto valore. Ripete anche le informazioni che sono già state presentate nella discussione.
Cindy Meister,

Grazie Cindy! Solo offrendo una soluzione!
Lindsay,

Ma ... questo in realtà non fa nulla. Non dovrebbe restituire qualcosa?
nnnnnn,

0

Forse questo? if (ourNumber% 2! == 0)


2
Mentre questo frammento di codice può risolvere la domanda, inclusa una spiegazione aiuta davvero a migliorare la qualità del tuo post. Ricorda che stai rispondendo alla domanda per i lettori in futuro e che queste persone potrebbero non conoscere i motivi del tuo suggerimento sul codice. Cerca anche di non aggiungere il tuo codice a commenti esplicativi, ciò riduce la leggibilità sia del codice che delle spiegazioni!
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);  
    }     
 }


Sebbene questo codice possa risolvere la domanda, inclusa una spiegazione di come e perché questo risolva il problema, contribuirebbe davvero a migliorare la qualità del tuo post e probabilmente a dare più voti positivi. Ricorda che stai rispondendo alla domanda per i lettori in futuro, non solo per la persona che chiede ora. Si prega di modificare la risposta per aggiungere spiegazioni e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
Daniil

-1

Per verificare se hai un numero pari o dispari, funziona anche.

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

Utilizzando il moderno stile javascript:

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'))ritorna vero. isEven('5')restituisce anche true. isOdd(NaN)genera un errore. :-(
RobG

Riparato isEven('5'). isOdd(NaN)probabilmente dovrebbe generare un errore.
Gunn,

1
L'host di script non dovrebbe gestire l'errore, la funzione dovrebbe. Mi è sempre stato detto che una discarica di base non è una normale conclusione . ;-)
RobG


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

quando 0 / anche voluto ma

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


Or return parseInt(n)%2===0?true:parseInt(n)===0. ma poi di nuovo, questo è lo stesso di molte altre risposte già qui.
Heretic Monkey,

1
Or return parseInt(n)%2 === 0 || parseInt(n) === 0. Ma perché analizzare ? Ciò restituisce true per valori come "32foo" e 12.5, che non sono pari.
RobG

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

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

1
quando sarà il promemoria di dividere un numero per 2 sarà 2?
user85421

Sì, hai ragione. Mi manca scrivere% 2 == 2. Mio male.
Dejan Markovic,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.