Тестування того, чи є значення непарним чи парним


173

Я вирішив створити просту функцію isEven і isOdd з дуже простим алгоритмом:

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

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

Це нормально, якщо n має певні параметри, але не вдається для багатьох сценаріїв. Тож я поставив собі за мету створити надійні функції, які дають правильні результати для стільки сценаріїв, скільки я міг, так що тільки цілі числа в межах номерів javascript перевіряються, а все інше повертає помилкові (включаючи + і - нескінченність). Зауважте, що нуль парний.

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

Чи може хтось бачити якісь проблеми з вищезазначеним? Чи є краща (тобто більш точна, швидша чи більш лаконічна версія, не будучи заплутаною) версією?

Існують різні публікації, що стосуються інших мов, але я не можу знайти остаточну версію для ECMAScript.


Відповіді:


368

Використовувати модуль:

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

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

Ви можете перевірити, що будь-яке значення в Javascript може бути приведене до числа за допомогою:

Number.isFinite(parseFloat(n))

Переважно цю перевірку слід робити поза функціями isEvenта isOddфункціями, тому вам не доведеться дублювати обробку помилок в обох функціях.


@Steve Так, але JS має деякі особливі проблеми, коли valueце не число або навіть якщо це число. Напр.: 0.1%2, NaN%2, []%2І т.д. Те , що ви написали у відповідь, він вже знає.
Алін Пуркару

1
0.1і NaNдобре працювати з функцією, наведеною вище. Порожній масив трохи болить, оскільки він дорівнює 0 ...
Стів Мейн

4
@Alin - я додав числовий чек. Я не впевнений, що розумію сценарій, коли ви хочете, щоб арифметична функція явно обробляла інші типи даних, але якщо цього хоче ОП ...
Стів Мейн,

2
Що про зміну return n == parseInt(n);на return n === parseInt(n);?
JiminP

2
Я думаю, я десь прочитав те, що слід перевірити, n % 2 !== 0перевіряючи непарні номери, оскільки це не обов'язково 1, залежно від мови. EDIT: Ах, саме для цього є .absзаклик. Не забудьте тоді.
ptf

79

Я вважаю за краще використовувати тест:

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

Це перевіряє, чи є перший біт, який позначає непарне число.


Корисний лише, якщо ви знаєте, що я - це номер, з якого слід почати. Неномери повинні повертатись невизначеними (а може бути помилкою, але невизначене здається розумним).
RobG

3
Абсолютно. Використання модуля для математики базової-2 повинно бути незаконним;)
aceofspades

4
Ternary: i & 1 == 1 ? console.log("odd") : console.log("even");Також +1 для ефективності бітового рівня (не настільки широко використовується в JS)
Jacksonkr

13
@Jacksonkr Зауважте, що в JavaScript не існує «ефективності бітового рівня», оскільки всі числа є плаваючими в JavaScript, а використання побітового оператора означає спершу перетворити його в int, потім виконати операцію, а потім перетворити її на номер з плаваючою комою.
ткнути

1
@poke Правильно, вони є типом Number, але приємно знати, що в сильно набраних мовах є ефективність.
Роберт Брізіта

8

Як щодо наступного? Я тестував це лише в IE, але він із задоволенням обробляв рядки, що представляють числа будь-якої довжини, фактичні числа, які були цілими чи плаваючими, і обидві функції поверталися помилковими, коли передавали булевий, невизначений, null, масив чи об'єкт. (Ви залежаєте від того, чи хочете ви проігнорувати провідні чи кінцеві пробіли, коли передається рядок - я припускав, що вони не ігноруються і викликають повернення обох функцій помилковими.)

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

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

2
Для моєї реалізації isEven (2.122e3) повертає true, але isEven ("2.122e3") повертає false. І навпаки, мій isEven () не вдається для дуже великих чисел, оскільки JS ставить їх у формат експоненту при перетворенні на рядок для тесту регулярного виразів. Що ж, добре.
nnnnnn

@MartijnScheffer - Не соромтеся надіслати мені рахунок за всю ту додаткову пам'ять, яку вам доведеться купувати. Зауважте, що запитання включало перетворення інших типів у число, і чітко, що тут я пропоную, - це мати просту однолінійну функцію, яка обробляє числа та рядки. Звичайно, на мій власний коментар, це насправді не обробляє всі можливі випадки, але це все ще може бути корисним - регулярний вираз є найпростішим способом перевірки даних, введених користувачем, які будуть початковою строкою.
nnnnnn

я опублікував тут коментар? я не бачу цього, але я можу, якщо ви хочете його! Це НЕ правильне рішення, це в сотні разів повільніше, і ми говоримо про числа, а не для рядків, якщо ви хочете перевірити, чи строка є дійсною число та ціле число, яке можна обробляти окремо.
Мартійн Шеффер

@MartijnScheffer - Так, коментар від вас був, здається, був видалений в якийсь момент з моєї відповіді. Зауважте, що питання стосувалося не лише чисел, код ОП включав перетворення інших типів. У будь-якому випадку, дякую за відгуки.
nnnnnn

7

Примітка: також є від’ємні числа.

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

де

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

1
Тут не потрібен розбір?
блаблабла

@blablabla Так, не всі реалізації припускають radix = 10.
Rodrigo

Хороше цитування негативних значень. Відповідь Роберта Брізіти (яка була додана пізніше) охоплює і це.
Jacksonkr

4

Чому б просто не зробити це:

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

Або навіть function isEven(num) { return num % 2 == 0}
chiapa

3
або з 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
if ( <expression> ) return true else return falseПарадигма може завжди бути спрощена return ( <expression> )(оскільки вираз в if уже завжди булева один).
Герольд Брозер

кажучи, що повернення не є функцією, це як сказати, якщо це не функція, цілком справедливо використовувати дужки при поверненні значення (навіть якщо вони тут не корисні)
Martijn Scheffer

1

Проста модифікація / вдосконалення відповіді Стіва Мейна!

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

Примітка: Повертає помилку, якщо недійсна!


1

Для цього нам знадобиться лише один рядок коду!

Ось новий і альтернативний спосіб зробити це, використовуючи новий синтаксис ES6 для функцій JS та однорядковий синтаксис для if-elseвиклику оператора:

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

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

1
Що коротше let isEven = num => num % 2 === 0. :-) Але насправді це не відрізняється від багатьох інших відповідей тут.
RobG

1

Декілька

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

Інший спосіб:

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

isEven(69)

0

Інакше використовуючи рядки, бо чому б ні

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

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

Без жодних пояснень ваш внесок не має великої цінності. Він також повторює інформацію, яка вже була представлена ​​в дискусії.
Сінді Майстер

Дякую Сінді! Просто пропонуємо рішення!
Ліндсей

Але ... це насправді нічого не робить . Чи не повинно щось повернути?
nnnnnn

0

Може, це? if (ourNumber% 2! == 0)


2
Хоча цей фрагмент коду може вирішити питання, зокрема пояснення дійсно допомагає покращити якість вашої публікації. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, і ці люди можуть не знати причини вашої пропозиції щодо коду. Будь ласка, намагайтеся не переповнювати свій код пояснювальними коментарями, це зменшує читабельність і коду, і пояснень!
Фільнор


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


Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються.
Даніїл

-1

Щоб перевірити, чи є у вас непарне або парне число, це також працює.

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

Використання сучасного стилю 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'))повертає правду. isEven('5')також повертає істину. isOdd(NaN)видає помилку. :-(
RobG

Виправлено isEven('5'). isOdd(NaN)напевно, слід викинути помилку.
gunn

1
Хост сценарію не повинен обробляти помилку, функція повинна. Мені завжди говорили, що основний дамп - це не нормальне припинення . ;-)
RobG


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

коли 0 / навіть хотів, але

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

Сігналы абмеркавання


Або return parseInt(n)%2===0?true:parseInt(n)===0. але знову ж таки, це те саме, що і багато інших відповідей, які вже є тут.
Єретична мавпа

1
Або return parseInt(n)%2 === 0 || parseInt(n) === 0. Але чому розбирати ? Це повертає істину для значень типу "32foo" і 12.5, які не є рівними.
RobG

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.