Как проверить, является ли целое число четным или нечетным?[закрыто]

StackOverflow https://stackoverflow.com/questions/160930

  •  03-07-2019
  •  | 
  •  

Вопрос

Как я могу проверить, является ли данное число четным или нечетным в C?

Это было полезно?

Решение

Используйте оператор по модулю (%), чтобы проверить, есть ли остаток при делении на 2:

if (x % 2) { /* x is odd */ }

Некоторые люди раскритиковали мой ответ выше, заявив, что использование x & 1 «быстрее» или «более эффективно».Я не верю, что это так.

Из любопытства я создал две тривиальные программы тестовых примеров:

/* modulo.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x % 2)
            printf("%d is odd\n", x);
    return 0;
}

/* and.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x & 1)
            printf("%d is odd\n", x);
    return 0;
}

Затем я 5 раз скомпилировал их с помощью gcc 4.1.3 на одной из своих машин:

  • Без флагов оптимизации.
  • С -О
  • С -Ос
  • С -O2
  • С -O3

Я исследовал выходные данные сборки каждой компиляции (с помощью gcc -S) и обнаружил, что в каждом случае выходные данные для and.c и modulo.c были идентичны (они оба использовали инструкцию andl $1, %eax).Я сомневаюсь, что это «новая» функция, и подозреваю, что она восходит к древним версиям.Я также сомневаюсь, что какой-либо современный (созданный за последние 20 лет) нормальный компилятор, коммерческий или с открытым исходным кодом, лишен такой оптимизации.Я бы протестировал на других компиляторах, но на данный момент у меня их нет.

Если кто-то еще захочет протестировать другие компиляторы и/или целевые платформы и получит другой результат, мне было бы очень интересно узнать.

Наконец, версия по модулю гарантированный по стандарту работать независимо от того, является ли целое число положительным, отрицательным или нулевым, независимо от представления целых чисел со знаком в реализации.Версия побитового И — нет.Да, я понимаю, что дополнение до двух встречается повсеместно, так что это не проблема.

Другие советы

Ребята, вы слишком эффективны.Чего вы действительно хотите:

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

Повторите для isEven.

Конечно, это не работает для отрицательных чисел.Но с блеском приходит жертва...

Используйте битовую арифметику:

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

Это быстрее, чем использование деления или модуля.

[Режим шутки = "вкл"]

public enum Evenness
{
  Unknown = 0,
  Even = 1,
  Odd = 2
}

public static Evenness AnalyzeEvenness(object o)
{

  if (o == null)
    return Evenness.Unknown;

  string foo = o.ToString();

  if (String.IsNullOrEmpty(foo))
    return Evenness.Unknown;

  char bar = foo[foo.Length - 1];

  switch (bar)
  {
     case '0':
     case '2':
     case '4':
     case '6':
     case '8':
       return Evenness.Even;
     case '1':
     case '3':
     case '5':
     case '7':
     case '9':
       return Evenness.Odd;
     default:
       return Evenness.Unknown;
  }
}

[Режим шутки = «выкл.»]

РЕДАКТИРОВАТЬ:В перечисление добавлены запутанные значения.

В ответ на ффпф - У меня был точно такой же спор с коллегой много лет назад, и ответ такой: нет, он не работает с отрицательными числами.

Стандарт C предусматривает, что отрицательные числа могут быть представлены тремя способами:

  • дополнение до 2
  • дополнение до 1
  • знак и величина

Проверяем так:

isEven = (x & 1);

будет работать для дополнения до 2 и представления знака и величины, но не для дополнения до 1.

Однако я считаю, что для всех случаев будет работать следующее:

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

Спасибо ffpf за указание на то, что текстовое поле съедает все после моего символа «меньше чем»!

Хороший вариант:

/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);

bool isEven(unsigned int n)
{
  if (n == 0) 
    return true ;  // I know 0 is even
  else
    return isOdd(n-1) ; // n is even if n-1 is odd
}

bool isOdd(unsigned int n)
{
  if (n == 0)
    return false ;
  else
    return isEven(n-1) ; // n is odd if n-1 is even
}

Обратите внимание, что этот метод использует хвостовую рекурсию, включающую две функции.Его можно эффективно реализовать (превратить в цикл while/пока), если ваш компилятор поддерживает хвостовую рекурсию, как компилятор Scheme.В этом случае стек не должен переполняться!

Число считается четным, если при его делении на два остаток равен 0.Число является нечетным, если при его делении на 2 остаток равен 1.

// Java
public static boolean isOdd(int num){
    return num % 2 != 0;
}

/* C */
int isOdd(int num){
    return num % 2;
}

Методы отличные!

i % 2 == 0

Я бы сказал, просто разделите его на 2, и если остаток равен 0, то он четный, в противном случае — нечетный.

Использование модуля (%) упрощает эту задачу.

например.4 % 2 = 0 Следовательно, 4 - это даже 5 % 2 = 1, поэтому 5 - нечетное

Еще одно решение проблемы
(дети могут голосовать)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}

Я бы построил таблицу четностей (0, если даже 1, если нечетно) целых чисел (чтобы можно было выполнить поиск: D), но gcc не позволит мне создавать массивы таких размеров:

typedef unsigned int uint;

char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;

void build_parity_tables () {
    char parity = 0;
    unsigned int ui;
    for (ui = 1; ui <= UINT_MAX; ++ui) {
        parity_uint [ui - 1] = parity;
        parity = !parity;
    }
    parity = 0;
    int si;
    for (si = 1; si <= INT_MAX; ++si) {
        parity_sint [si - 1] = parity;
        parity = !parity;
    }
    parity = 1;
    for (si = -1; si >= INT_MIN; --si) {
        parity_sint [si] = parity;
        parity = !parity;
    }
}

char uparity (unsigned int n) {
    if (n == 0) {
        return 0;
    }
    return parity_uint [n - 1];
}

char sparity (int n) {
    if (n == 0) {
        return 0;
    }
    if (n < 0) {
        ++n;
    }
    return parity_sint [n - 1];
}

Итак, давайте вместо этого обратимся к математическому определению четного и нечетного.

Целое число n является четным, если существует целое число k такое, что n = 2k.

Целое число n является нечетным, если существует целое число k такое, что n = 2k + 1.

Вот код для этого:

char even (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k) {
            return 1;
        }
    }
    return 0;
}

char odd (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k + 1) {
            return 1;
        }
    }
    return 0;
}

Пусть C-целые числа обозначают возможные значения int в данной компиляции C.(Обратите внимание, что C-целые числа — это подмножество целых чисел.)

Теперь можно беспокоиться, что для данного n в C-целых числах соответствующее целое число k может не существовать в C-целых числах.Но с небольшим доказательством можно показать, что для всех целых чисел n, | n | <= | 2n | (*), где | n | «это" n, если n положительный и -н, в противном случае ".Другими словами, для всех n в целых числах имеет место хотя бы одно из следующих утверждений (фактически либо случаи (1 и 2), либо случаи (3 и 4), но я не буду это доказывать здесь):

Дело 1:п <= 2п.

Случай 2:-n <= -2n.

Случай 3:-н ​​<= 2н.

Случай 4:п <= -2n.

Теперь возьмем 2k = n.(Такое k существует, если n четно, но я не буду это доказывать здесь.Если n не четно, то цикл в even в любом случае не может вернуться раньше, так что это не имеет значения.) Но это подразумевает k < n, если n не 0 согласно (*), и тот факт (опять здесь не доказан), что для всех m, z в целых числах 2m = z подразумевает z не равно m, если m не равно 0.В случае, когда n равно 0, 2*0 = 0, поэтому 0 — четное, и мы закончили (если n = 0, то 0 находится в C-целых числах, потому что n находится в C-целых числах в функции even, следовательно, k = 0 записано в C-целых числах).Таким образом, такой k в C-целых числах существует для n в C-целых числах, если n четно.

Аналогичный аргумент показывает, что если n нечетно, существует k в C-целых числах такое, что n = 2k + 1.

Следовательно, функции even и odd представленный здесь, будет работать правильно для всех C-целых чисел.

// C#
bool isEven = ((i % 2) == 0);

Вот ответ на Java:

public static boolean isEven (Integer Number) {
    Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
    String num = Number.toString(Number);
    Boolean numbr = new Boolean(number.matcher(num).matches());
    return numbr.booleanValue();
}

Попробуй это: return (((a>>1)<<1) == a)

Пример:

a     =  10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100

Читая это довольно интересное обсуждение, я вспомнил, что у меня есть реальная, чувствительная ко времени функция, которая проверяет нечетные и четные числа внутри основного цикла.Это целочисленная степенная функция, опубликованная в другом месте на StackOverflow, как показано ниже.Тесты оказались весьма неожиданными.По крайней мере, в этой реальной функции, по модулю медленнее, и это существенно. Победителем с большим отрывом, требующим 67% времени по модулю, является подход или ( | ), и его нигде больше нет на этой странице.

static dbl  IntPow(dbl st0, int x)  {
    UINT OrMask = UINT_MAX -1;
    dbl  st1=1.0;
    if(0==x) return (dbl)1.0;

    while(1 != x)   {
        if (UINT_MAX == (x|OrMask)) {     //  if LSB is 1...    
        //if(x & 1) {
        //if(x % 2) {
            st1 *= st0;
        }    
        x = x >> 1;  // shift x right 1 bit...  
        st0 *= st0;
    }
    return st1 * st0;
}

Для 300 миллионов циклов контрольные значения времени следующие.

3.962 | и маска подход

4.851 & подход

5.850% подход

Для людей, которые думают, что теория или список языков ассемблера разрешают подобные аргументы, это должно стать предостережением.На небе и на земле, Горацио, есть больше вещей, чем мечтает твоя философия.

Это продолжение обсуждения с @RocketRoy относительно его ответ, но это может быть полезно всем, кто хочет сравнить эти результаты.

TL; доктор Судя по тому, что я видел, подход Роя ((0xFFFFFFFF == (x | 0xFFFFFFFE)) не полностью оптимизирован для x & 1 как mod подход, но на практике время работы во всех случаях должно оказаться одинаковым.

Итак, сначала я сравнил скомпилированный результат, используя Компилятор Explorer:

Проверенные функции:

int isOdd_mod(unsigned x) {
    return (x % 2);
}

int isOdd_and(unsigned x) {
    return (x & 1);
}

int isOdd_or(unsigned x) {
    return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}   

CLang 3.9.0 с -O3:

isOdd_mod(unsigned int):                          # @isOdd_mod(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_and(unsigned int):                          # @isOdd_and(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_or(unsigned int):                           # @isOdd_or(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

GCC 6.2 с -O3:

isOdd_mod(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_and(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_or(unsigned int):
        or      edi, -2
        xor     eax, eax
        cmp     edi, -1
        sete    al
        ret

С уважением относимся к CLang: они поняли, что все три случая функционально равны.Однако подход Роя не оптимизирован в GCC, поэтому YMMV.

То же самое и с Visual Studio;проверяя выпуск дизассемблирования x64 (VS2015) для этих трех функций, я мог видеть, что часть сравнения одинакова для случаев «мод» и «и» и немного больше для случая Роя «или»:

// x % 2
test bl,1  
je (some address) 

// x & 1
test bl,1  
je (some address) 

// Roy's bitwise or
mov eax,ebx  
or eax,0FFFFFFFEh  
cmp eax,0FFFFFFFFh  
jne (some address)

Однако после запуска фактического теста для сравнения этих трех вариантов (обычный мод, побитовый или побитовый и) результаты оказались полностью одинаковыми (опять же, Visual Studio 2005 x86/x64, сборка Release, без подключенного отладчика).

Сборка выпуска использует test инструкция для and и mod случаях, в то время как в случае Роя используется cmp eax,0FFFFFFFFh подход, но он сильно развернут и оптимизирован, поэтому на практике разницы нет.

Мои результаты после 20 запусков (i7 3610QM, план электропитания Windows 10 установлен на «Высокая производительность»):

[Test: Plain mod 2 ] AVERAGE TIME: 689.29 ms (Relative diff.: +0.000%)
[Test: Bitwise or  ] AVERAGE TIME: 689.63 ms (Relative diff.: +0.048%)
[Test: Bitwise and ] AVERAGE TIME: 687.80 ms (Relative diff.: -0.217%)

Разница между этими вариантами составляет менее 0,3%, поэтому вполне очевидно, что сборка во всех случаях одинакова.

Вот код, если кто-то захочет попробовать, с оговоркой, что я тестировал его только на Windows (проверьте #if LINUX условно для get_time определение и реализовать его при необходимости, взято из этот ответ).

#include <stdio.h>

#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
    struct timeval t;
    struct timezone tzp;
    gettimeofday(&t, &tzp);
    return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
    LARGE_INTEGER t, f;
    QueryPerformanceCounter(&t);
    QueryPerformanceFrequency(&f);
    return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif

#define NUM_ITERATIONS (1000 * 1000 * 1000)

// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
    double startTime = get_time(); \
    double dummySum = 0.0, elapsed; \
    int x; \
    for (x = 0; x < NUM_ITERATIONS; x++) { \
        if (operation) dummySum += x; \
    } \
    elapsed = get_time() - startTime; \
    accumulator += elapsed; \
    if (dummySum > 2000) \
        printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}

void DumpAverage(char *test, double totalTime, double reference)
{
    printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
        test, totalTime, (totalTime - reference) / reference * 100.0);
}

int main(void)
{
    int repeats = 20;
    double runningTimes[3] = { 0 };
    int k;

    for (k = 0; k < repeats; k++) {
        printf("Run %d of %d...\r\n", k + 1, repeats);
        Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
        Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
        Benchmark(runningTimes[2], "Bitwise and", (x & 1));
    }

    {
        double reference = runningTimes[0] / repeats;
        printf("\r\n");
        DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
        DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
        DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
    }

    getchar();

    return 0;
}

Я знаю, что это всего лишь синтаксический сахар и применимо только в .net а как насчет метода расширения...

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

Теперь вы можете сделать следующее

int i = 5;
if (i.IsOdd())
{
    // Do something...
}

В категории «креативно, но запутанно» предлагаю:

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

Вариант этой темы, специфичный для Microsoft C++:

__declspec(naked) bool __fastcall isOdd(const int x)
{
    __asm
    {
        mov eax,ecx
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        ret
    }
}

Побитовый метод зависит от внутреннего представления целого числа.Модуль будет работать везде, где есть оператор модуля.Например, некоторые системы фактически используют биты низкого уровня для тегирования (например, динамические языки), поэтому необработанные x и 1 в этом случае фактически не будут работать.

IsOdd(int x) { return true;}

Доказательство правильности: рассмотрим набор всех положительных целых чисел и предположим, что существует непустой набор нечетных целых чисел.Поскольку положительные целые числа хорошо упорядочены, будет наименьшее нечетное число, что само по себе довольно нечетно, поэтому очевидно, что это число не может быть в наборе.Следовательно, это множество не может быть непустым.Повторите то же самое для отрицательных целых чисел, но ищите наибольшее нечетное число.

Портативный:

i % 2 ? odd : even;

Непереносимый:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;

Как писали некоторые люди, существует множество способов сделать это.В соответствии с этот сайт, самый быстрый способ — это оператор модуля:

if (x % 2 == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

Однако вот некоторые другой код, отмеченный на стенде автором, который работал медленнее, чем описанная выше операция с общим модулем:

if ((x & 1) == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

System.Math.DivRem((long)x, (long)2, out outvalue);
        if ( outvalue == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x / 2) * 2) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x >> 1) << 1) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

        while (index > 1)
               index -= 2;
        if (index == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

tempstr = x.ToString();
        index = tempstr.Length - 1;
        //this assumes base 10
        if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
               total += 1; //even number
        else
               total -= 1; //odd number

Сколько людей вообще знали о Math.System.DivRem метод или зачем им его использовать??

int isOdd(int i){
  return(i % 2);
}

сделанный.

Чтобы подробнее рассказать о методе побитовых операторов для тех из нас, кто мало занимался булевой алгеброй во время учебы, вот объяснение.Вероятно, это не принесет особой пользы ОП, но мне хотелось прояснить, почему NUMBER & 1 работает.

Обратите внимание, что, как кто-то ответил выше, способ представления отрицательных чисел может помешать работе этого метода.Фактически, это может даже нарушить метод оператора по модулю, поскольку каждый язык может по-разному обращаться с отрицательными операндами.

Однако если вы знаете, что ЧИСЛО всегда будет положительным, это работает хорошо.

Как Туони выше отметил, что важна только последняя цифра в двоичной (и десятичной) системе.

Логический логический элемент И требует, чтобы на обоих входах была 1 (или высокое напряжение), чтобы 1 была возвращена.

1 & 0 = 0.

0 & 1 = 0.

0 & 0 = 0.

1 & 1 = 1.

Если вы представляете любое число в двоичном виде (здесь я использовал 8-битное представление), нечетные числа имеют в конце 1, четные числа имеют 0.

Например:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Если вы возьмете любое число и используете побитовое И (& в Java) на 1, оно либо вернет 00000001, = 1, что означает, что число нечетное.Или 00000000 = 0, что означает, что число четное.

Например

Странно?

1 & 1 =

00000001 &

00000001 =

00000001 <— Нечетный

2 & 1 =

00000010 &

00000001 =

00000000 <— четный

54 & 1 =

00000001 &

00110110 =

00000000 <— четный

Вот почему это работает:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Извините, если это лишнее.

Номер нулевой паритет | нуль http://tinyurl.com/oexhr3k

Последовательность кода Python.

# defining function for number parity check
def parity(number):
    """Parity check function"""
    # if number is 0 (zero) return 'Zero neither ODD nor EVEN',
    # otherwise number&1, checking last bit, if 0, then EVEN, 
    # if 1, then ODD.
    return (number == 0 and 'Zero neither ODD nor EVEN') \
            or (number&1 and 'ODD' or 'EVEN')

# cycle trough numbers from 0 to 13 
for number in range(0, 14):
    print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))

Выход:

   0 : 00000000 : Zero neither ODD nor EVEN
   1 : 00000001 : ODD
   2 : 00000010 : EVEN
   3 : 00000011 : ODD
   4 : 00000100 : EVEN
   5 : 00000101 : ODD
   6 : 00000110 : EVEN
   7 : 00000111 : ODD
   8 : 00001000 : EVEN
   9 : 00001001 : ODD
  10 : 00001010 : EVEN
  11 : 00001011 : ODD
  12 : 00001100 : EVEN
  13 : 00001101 : ODD
I execute this code for ODD & EVEN:

#include <stdio.h>
int main()
{
    int number;
    printf("Enter an integer: ");
    scanf("%d", &number);

    if(number % 2 == 0)
        printf("%d is even.", number);
    else
        printf("%d is odd.", number);
}

Ради обсуждения...

Вам нужно только посмотреть на последнюю цифру любого числа, чтобы определить, четное оно или нечетное.Знаковые, беззнаковые, положительные, отрицательные – в этом отношении они все одинаковы.Итак, это должно работать со всех сторон:-

void tellMeIfItIsAnOddNumberPlease(int iToTest){
  int iLastDigit;
  iLastDigit = iToTest - (iToTest / 10 * 10);
  if (iLastDigit % 2 == 0){
    printf("The number %d is even!\n", iToTest);
  } else {
    printf("The number %d is odd!\n", iToTest);
  }
}

Ключевым моментом здесь является третья строка кода: оператор деления выполняет целочисленное деление, поэтому в результате отсутствует дробная часть результата.Так например 222/10 в результате даст 22.Затем умножьте это число еще раз на 10, и вы получите 220.Вычтите это из исходных 222, и вы получите 2, которые по волшебству совпадают с последней цифрой исходного числа.;-) Сестрае есть, чтобы напомнить нам о заказе, в котором делается расчет.Сначала выполните деление и умножение, затем вычтите результат из исходного числа.Мы могли бы их исключить, поскольку приоритет деления и умножения выше, чем вычитания, но это дает нам «более читаемый» код.

Если бы мы захотели, мы могли бы сделать все это совершенно нечитаемым.Для современного компилятора это не имело бы никакого значения:-

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

Но это усложнит поддержку кода в будущем.Представьте себе, что вы хотите изменить текст для нечетных чисел на «не чет».Затем кто-нибудь позже захочет узнать, какие изменения вы внесли, и выполнить svn diff или что-то подобное...

Если вас больше беспокоит не портативность, а скорость, вы можете взглянуть на наименее значимую часть.Если этот бит установлен в 1, это нечетное число, если он равен 0, это четное число.В системе с прямым порядком байтов, например в архитектуре Intel x86, это будет примерно так:-

if (iToTest & 1) {
  // Even
} else {
  // Odd
}

Если вы хотите быть эффективными, используйте побитовые операторы (x & 1), но если вы хотите, чтобы его читали, используйте модуль 2 (x % 2)

Проверка четности или нечетности — простая задача.

Мы знаем, что любое число, делящееся точно на 2, является четным, иначе – нечетным.

Нам просто нужно проверить делимость любого числа и для проверки делимости мы используем % оператор

Проверка четности и нечетности с помощью if else

if(num%2 ==0)  
{
    printf("Even");
}
else
{
    printf("Odd");
}

Программа C для проверки четности или нечетности с помощью if else

Использование условного/троичного оператора

(num%2 ==0) printf("Even") : printf("Odd");

Программа C для проверки четности или нечетности с использованием условного оператора.

Использование побитового оператора

if(num & 1)  
{
    printf("Odd");
}
else 
{
    printf("Even");
}

+66% быстрее > !(i%2) / i%2 == 0

int isOdd(int n)
{
    return n & 1;
}

Код проверяет последний бит целого числа, если оно 1 в двоичном формате

Объяснение

Binary  :   Decimal
-------------------
0000    =   0
0001    =   1
0010    =   2
0011    =   3
0100    =   4
0101    =   5
0110    =   6
0111    =   7
1000    =   8
1001    =   9
and so on...

Уведомление самый правый кусочек всегда 1 для Странный цифры.

тот & побитовый оператор AND проверяет самый правый бит в нашем возвращаться линия, если она 1

Думайте об этом как об истинном и ложном

Когда мы сравниваем н с 1 что значит 0001 в двоичном формате (количество нулей не имеет значения).
тогда давайте просто представим, что у нас есть целое число н размером 1 байт.

Он будет представлен 8-битными/8-двоичными цифрами.

Если int н был 7 и мы сравниваем его с 1, Это как

7 (1-byte int)|    0  0  0  0    0  1  1  1
       &
1 (1-byte int)|    0  0  0  0    0  0  0  1
********************************************
Result        |    F  F  F  F    F  F  F  T

Который Ф означает ложь и Т для правды.

Это сравнивает только самый правый бит, если они оба верны.Итак, автоматически 7 & 1 является Тулица.

Что делать, если я хочу проверить бит перед самым правым?

Просто измените n & 1 к n & 2 который 2 представляет 0010 в двоичном формате и так далее.

Я предлагаю использовать шестнадцатеричную запись, если вы новичок в побитовых операциях.
return n & 1; >> return n & 0x01;.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top