Bir değerin tek veya çift olup olmadığını test etme


173

Çok basit bir algoritma ile basit isEven ve isOdd işlevi oluşturmaya karar verdim :

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

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

N belirli parametrelerde ise, ancak birçok senaryoda başarısız olursa sorun olmaz. Bu yüzden olabildiğince çok senaryo için doğru sonuçlar veren sağlam işlevler oluşturmaya başladım, böylece sadece javascript sayılarının sınırları içindeki tamsayılar test edildi, diğer her şey yanlış (+ ve - sonsuz dahil) döndürür. Sıfırın çift olduğunu unutmayın.

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

Yukarıdakilerle ilgili herhangi bir sorun gören var mı? Daha iyi (gizlenmiş olmadan daha doğru, daha hızlı veya daha kısa) bir sürüm var mı?

Diğer dillerle ilgili çeşitli yayınlar var, ancak ECMAScript için kesin bir sürüm bulamıyorum.


Yanıtlar:


368

Modülü kullan:

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

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

Javascript'teki herhangi bir değerin aşağıdakilerle bir sayıya zorlanıp zorlanamayacağını kontrol edebilirsiniz:

Number.isFinite(parseFloat(n))

Bu kontrol tercihen isEvenve isOddişlevlerinin dışında yapılmalıdır , böylece her iki işlevde de hata işlemeyi çoğaltmanız gerekmez.


@Steve Evet, ancak valuebir sayı olmadığında veya bir sayı olsa bile JS'nin bazı özel sorunları var. Örn .: 0.1%2, NaN%2, []%2, vb cevap yazdı Ne, o zaten bunu biliyor.
Alin Purcaru

1
0.1ve NaNyukarıdaki işlevle iyi çalışır. Boş dizi 0 olduğu gibi bir acı biraz ...
Steve Mayne

4
@Alin - Sayısal bir kontrol ekledim. Aritmetik bir işlevin diğer veri türlerini açıkça işlemesini istediğinizde senaryoyu anladığımdan emin değilim, ancak OP'nin istediği buysa ...
Steve Mayne

2
Değişmek ne return n == parseInt(n);olacak return n === parseInt(n);?
JiminP

2
n % 2 !== 0Tek sayıları kontrol ederken neyi kontrol etmeniz gerektiğini bir yere okuduğumu düşünüyorum , çünkü dile bağlı olarak mutlaka 1 değil. EDIT: Ah, .absçağrı bunun için. Boşver o zaman.
ptf

79

Bir bit testi kullanmayı tercih ederim:

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

Bu, tek bir sayıyı gösteren ilk bitin açık olup olmadığını test eder.


Sadece i ile başlamak için bir sayı olduğunu biliyorsanız yararlıdır . Sayı olmayanlar tanımsız olarak dönmelidir (veya belki bir hata atmalıdır , ancak tanımsız mantıklı görünüyor).
Mart'ta RobG 0:15

3
Kesinlikle. Yasadışı olmalıdır taban-2 matematik için modülünü kullanarak;)
aceofspades'ait

4
Üçlü: i & 1 == 1 ? console.log("odd") : console.log("even");Ayrıca, bit seviyesi verimliliği için +1 (JS'de yaygın olarak kullanılmaz)
Jacksonkr 15:17

13
@Jacksonkr Tüm sayıların JavaScript'te kayan ve bitsel bir işleç kullanılması ilk önce bir int'e dönüştürmek, sonra işlemi gerçekleştirmek ve daha sonra bir kayan nokta numarasına dönüştürmek anlamına geldiğinden, JavaScript'te “bit seviyesi verimliliği” olmadığını unutmayın.
dürtmek

1
@poke Number türünde olduklarını düzeltin, ancak güçlü yazılan dillerde verimlilik olduğunu bilmek güzel.
Robert Brisita

8

Aşağıdakilere ne dersiniz? Bunu sadece IE'de test ettim, ancak herhangi bir uzunluktaki sayıları, tamsayı veya kayan gerçek sayıları temsil eden dizeleri işlemek oldukça mutluydu ve her iki işlev de bir boole, tanımsız, boş, bir dizi veya bir nesne geçtiğinde yanlış döndü. (Bir dize iletildiğinde önde gelen veya sondaki boşlukları yoksaymak isteyip istemediğiniz size kalmış - yok sayılmadıklarını ve her iki işlevin de yanlış dönmesine neden olduğunu varsaydım .)

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

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

2
Benim uygulama için isEven (2.122e3) doğru döndürür, ancak isEven ("2.122e3") yanlış döndürür. Tersine benim isEven () gerçekten büyük sayılar için başarısız çünkü JS regex testi için dizeye dönüştürürken onları üs biçiminde koyar. Oh iyi.
nnnnnn

@MartijnScheffer - Satın almanız gereken tüm ekstra bellek için faturayı bana göndermekten çekinmeyin. Sorunun diğer türlerden sayıya dönüşümleri içerdiğini ve burada önerdiğim şeyin sayıları ve dizeleri işleyen basit bir tek satır işlevine sahip olduğunu açıkça unutmayın . Tabii ki, kendi yorumuma göre bu aslında tüm olası durumları ele almıyor, ancak yine de yararlı olabilir - regex, başlangıçta bir dize olacak olan, kullanıcı tarafından girilen verileri doğrulamanın en basit yoludur.
nnnnnn

buraya yorum gönderdim mi? ben görmüyorum, ama bir tane istiyorsanız yapabilirim!, bu doğru bir çözüm DEĞİL, bu yüzlerce kez daha yavaş ve biz bir dizenin geçerli olup olmadığını kontrol etmek istiyorsanız, dizeleri değil, sayılar hakkında konuşuyoruz sayı ve ayrı ayrı işlenebilen bir tam sayı.
Martijn Scheffer

@MartijnScheffer - Evet, sizden bir yorum vardı, cevabımdan beri bir noktada silinmiş gibi görünüyor. Sorunun sadece sayılarla ilgili olmadığını, OP kodunun diğer türlerden dönüşümleri içerdiğini unutmayın. Neyse, geri bildiriminiz için teşekkürler.
nnnnnn

7

Not: negatif sayılar da vardır.

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

nerede

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

1
Burada ayrıştırmaya gerek yok mu?
blablabla

@blablabla Evet, tüm uygulamalar sayı tabanı = 10 kabul etmiyor
Rodrigo

Negatif değerlere iyi atıf. Robert Brisita'nın yanıtı (daha sonra eklenmiştir) de bunu kapsamaktadır.
Jacksonkr

4

Neden sadece bunu yapmıyorsunuz:

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

Veya çift function isEven(num) { return num % 2 == 0}
chiapa

3
veya ES6 ile: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
if ( <expression> ) return true else return falseParadigma olabilir hep basitleştirilebilir return ( <expression> )(bir in ifadesi beri if zaten hep bir boolean biridir).
Gerold Broser

dönüşün bir işlev olmadığını söylemek, bir işlev değilse, bir değer döndürürken parantez kullanmak için mükemmel bir şekilde geçerli olduğunu söylemek gibidir (burada yararlı olmasalar bile)
Martijn Scheffer

1

Steve Mayne cevap basit bir değişiklik / iyileştirme!

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

Not: Geçersizse false döndürür!


1

Bunun için sadece bir kod satırına ihtiyacımız var!

Burada JS işlevleri için yeni ES6 sözdizimini ve deyim çağrısı için tek satır sözdizimini kullanarak bunu yapmanın daha yeni ve alternatif bir yolu if-else:

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

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

1
Hangi daha kısadır let isEven = num => num % 2 === 0. :-) Ama gerçekten buradaki diğer birçok cevaptan farklı değil.
RobG

1

Birkaç

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

Farklı yol:

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

isEven(69)

0

Aksi halde dizeleri kullanıyor çünkü neden olmasın

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

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

Hiçbir açıklama yapmadan katkınızın fazla bir değeri yoktur. Ayrıca, tartışmada zaten sunulan bilgileri tekrarlar.
Cindy Meister

Teşekkürler Cindy! Sadece bir çözüm sunuyor!
Lindsay

Ama ... bu aslında hiçbir şey yapmıyor. Bir şey döndürmemeli mi?
nnnnnn

0

Belki bu? eğer (ourNumber% 2! == 0)


2
Bu kod snippet'i soruyu çözebilir, ancak bir açıklama da dahil olmak üzere , yayınınızın kalitesini artırmaya yardımcı olur. Gelecekte okuyucular için soruyu cevapladığınızı ve bu kişilerin kod önerinizin nedenlerini bilmeyebileceğini unutmayın. Lütfen kodunuzu açıklayıcı yorumlarla doldurmamaya çalışın, bu hem kodun hem de açıklamaların okunabilirliğini azaltır!
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);  
    }     
 }


Bu kod, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere soruyu çözebilir, ancak gönderinizin kalitesini artırmaya yardımcı olabilir ve muhtemelen daha fazla oyla sonuçlanır. Sadece şimdi soran kişi için değil, gelecekte okuyucular için soruyu cevapladığınızı unutmayın. Lütfen açıklama eklemek için cevabınızı düzenleyin ve hangi sınırlamaların ve varsayımların geçerli olduğunu belirtin.
Daniil

-1

Tek ya da çift bir numaranız olup olmadığını test etmek için bu da işe yarar.

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

Modern javascript stilini kullanarak:

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'))true değerini döndürür. isEven('5')ayrıca doğru döndürür. isOdd(NaN)hata veriyor. :-(
RobG

Düzeltildi isEven('5'). isOdd(NaN)muhtemelen bir hata atmalıdır.
gunn

1
Komut dosyası barındırıcısı hatayı işlememeli, işlev olmalıdır. Bana her zaman bir çekirdek dökümü normal bir sonlandırma olmadığı söylendi . ;-)
RobG


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

0 / hatta istediğinde

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


Veya return parseInt(n)%2===0?true:parseInt(n)===0. ama sonra tekrar, bu zaten burada bulunan diğer cevapların çoğu ile aynı.
Heretic Monkey

1
Veya return parseInt(n)%2 === 0 || parseInt(n) === 0. Ama neden ayrıştırılıyor ? Bu, "32foo" gibi ve 12.5çift ​​olmayan değerler için true değerini döndürür .
RobG

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

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

1
herhangi bir sayıyı 2'ye bölme hatırlatıcısı ne zaman 2 olur?
user85421

Hm, evet haklısın. % 2 == 2 yazmayı özledim.
Dejan Markovic
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.