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

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

30 ответов


используйте оператор по модулю ( % ), чтобы проверить, есть ли остаток при делении на 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 были идентичны (они оба использовали инструкцию andl $1, %eax). Я сомневаюсь, что это" новая " функция, и я подозреваю, что она восходит к древним версиям. Я также сомневаюсь в любом современном (сделанном за последние 20 лет) не-тайном компиляторе, коммерческом или open source, не хватает такой оптимизации. Я бы тестировал на других компиляторах, но на данный момент у меня нет доступных.

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

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


вы, ребята, waaaaaaaay слишком эффективны. То, что вы действительно хотите:

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

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


[режим шутки= "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;
  }
}

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

EDIT: добавлены запутанные значения в перечисление.


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

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

  • дополнение 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/until), если ваш компилятор поддерживает хвостовую рекурсию, как компилятор схемы. В этом случае стек не должен переполняться !


число, даже если, при делении на два остаток равен 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-integers является подмножеством целых чисел.)

теперь можно беспокоиться, что для данного n в C-целых числах соответствующее целое число k может не существовать в C-целых числах. Но с небольшим доказательством можно показать, что для всех целых чисел n, |n|

Случай 1: n

случай 2: - n

Случай 3: - n

случай 4: n

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

аналогичный аргумент показывает, что если N нечетно, существует k в 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

сколько людей даже знали о математика.Система.DivRem способ или почему они его используют??


вот ответ 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

по модулю медленнее, причем значительно. победителем, с большим отрывом, требующим 67% времени по модулю, является подход or ( / ), и нигде больше на этой странице.

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 & approach

5.850 в % подход

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


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

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

Итак, сначала я сравнил скомпилированный вывод с помощью компилятор Исследователь!--17-->:

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

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

лязг 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

шляпы вниз, чтобы Лязгнуть, он понял, что все три случая функционально равны. Однако подход Роя не оптимизирован в GCC, поэтому YMMV.

это похоже на Visual Studio; проверка разборки выпуска x64 (VS2015) для этих трех функций, Я мог видеть, что часть сравнения равна для" mod "и" и "случаев, и немного больше для" Roy'S " или " case:

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

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

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

мои результаты после 20 запусков (i7 3610QM, Windows 10 Power plan установлен на высокую производительность):

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

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


IsOdd (int x) { return true;}

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


портативное:

i % 2 ? odd : even;

Unportable:

i & 1 ? odd : even;

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

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

сделано.


чтобы дать более подробную информацию о побитовом операторном методе для тех из нас, кто не делал много булевой алгебры во время наших исследований, вот объяснение. Вероятно, не очень полезно для OP, но я чувствовал, что хочу прояснить, почему работает 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, что означает, что число четное.

Е. Г

Is странно?

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, это четное число. На маленькой системе endian, такой как архитектура x86 Intel, это было бы что-то вроде этого: -

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

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


проверка четных или нечетных-простая задача.

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

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

проверка даже нечетное использование, если еще

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 для странно цифры.

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

думайте об этом как true & false

когда мы сравниваем n С 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 означает false и T для true.

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

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

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

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