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

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

31 ответ

Решение

Используйте оператор по модулю (%), чтобы проверить, есть ли остаток при делении на 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;
}

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

  • Без флагов оптимизации.
  • С -O
  • С -Os
  • С -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");

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

[Joke mode = "on"]

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

[Joke mode = "off"]

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

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

Стандарт 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
}

Обратите внимание, что этот метод использует хвостовую рекурсию с участием двух функций. Это может быть эффективно реализовано (превращено в цикл время / пока), если ваш компилятор поддерживает хвостовую рекурсию, как компилятор 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 в противном случае". Другими словами, для всех n в целых числах выполняется, по крайней мере, одно из следующих (в действительности, точно либо случаи (1 и 2), либо случаи (3 и 4), но я не буду здесь это доказывать):

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

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

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

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

Теперь возьмите 2k = n. (Такой ak существует, если n четное, но я не буду здесь это доказывать. Если n не четное, то цикл в even в любом случае не удается вернуть рано, поэтому это не имеет значения.) Но это подразумевает, что k evenследовательно, k = 0 в C-целых числах). Таким образом, такое ak в C-целых числах существует для n в C-целых числах, если n четное.

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

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

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

Как пишут некоторые люди, есть множество способов сделать это. Согласно этому сайту, самый быстрый способ - это оператор модуля:

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 или почему они его используют??

Читая это довольно занимательное обсуждение, я вспомнил, что у меня была реальная, чувствительная ко времени функция, которая проверяла нечетные и четные числа внутри основного цикла. Это целочисленная функция мощности, размещенная в другом месте в Stackru следующим образом. Тесты были довольно удивительными. По крайней мере, в этой реальной функции модуль медленнее, и это значительно. Победителем, с большим отрывом, требующим 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% подход

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

Вот ответ на 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();
}

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

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

Итак, сначала я сравнил скомпилированный вывод, используя Compiler 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) для этих трех функций, я увидел, что часть сравнения равна для случаев "mod" и " and ", и немного больше для случая "Roy's" или ":

// 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, сборка выпуска, отладчик не подключен).

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

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

[Тест: Обычный мод 2 ] СРЕДНЕЕ ВРЕМЯ: 689,29 мс (Относительная разница: +0,000%)
[Тест: побитовый или] СРЕДНЕЕ ВРЕМЯ: 689,63 мс (Относительная разница: +0,048%)
[Тест: побитовый и] СРЕДНЕЕ ВРЕМЯ: 687.80 мс (Относительная разница: -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;
}

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

Пример:

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

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

Я знаю, что это просто синтаксический сахар и применим только в.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
    }
}

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

IsOdd(int x) { return true; }

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

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

i % 2 ? odd : even;

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

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;
int isOdd(int i){
  return(i % 2);
}

сделанный.

Число Ноль паритет | ноль 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);
}

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

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

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

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

Логический логический элемент И требует, чтобы оба входа были равны 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
}

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

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

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

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
}

+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 для нечетных чисел.

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

Думайте об этом как о правде и лжи

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

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

Если int n было 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

Который F обозначает ложь, а T - истину.

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

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

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

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

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

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

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

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

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

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

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

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

Программа на С проверяет четность или нечетность с помощью условного оператора.

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

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

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

Другие вопросы по тегам