Как я могу проверить, является ли данное число четным или нечетным в C?
Как я могу проверить, является ли данное число четным или нечетным в 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;
}
Затем я скомпилировал их с помощью gcc 4.1.3 на одной из моих машин 5 раз:
Я проверил вывод сборки каждого компилятора (используя 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 предусматривает, что отрицательные числа могут быть представлены тремя способами:
Проверка как это:
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 <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-целых числах). Таким образом, такое ak в C-целых числах существует для n в C-целых числах, если n четное.
Аналогичный аргумент показывает, что если n нечетно, существует ak в C-целых числах, такое что n = 2k + 1.
Следовательно, функции even
и odd
представленные здесь будут работать правильно для всех C-целых чисел.
i % 2
намного меньше и, вероятно, более эффективно.
%2
работает для всех целых чисел.
// C#
bool isEven = ((i % 2) == 0);
typedef
или #define
или что-то.
Вот ответ на 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% подход
Для людей, которые думают, что теория или листинг на ассемблере приводят подобные аргументы, это должно быть предостерегающим рассказом. Горацио, на небесах и на земле больше вещей, о которых ты и не мечтал в своей философии.
unsigned x
как x = x >> 1;
поведение, определяемое реализацией, когда x < 0
. Непонятно почему x
и OrMask
отличаются по типу. Достаточно просто переписать с помощью while(x)
теста.
% 2
регистр с использованием побитового кода &
. Я только что проверил это, и результаты полностью совпадают (VS2015, Релиз сборки со всеми оптимизациями, как x86, так и x64). В принятом ответе также указано это для GCC (написано в 2008 году).
or
будет быстрее, чем and
очень маловероятно, на любой платформе / компиляторе. Даже если бы была такая странная комбинация платформы / компилятора (и вы не опубликовали ни того, ни кода, используемого для выполнения теста), зависеть от поведения других компиляторов будет плохой ставкой на оптимизацию. Итак, как я уже писал, мне интересно, на какой платформе / компиляторе это тестировалось , потому что я почти уверен, что он не был измерен правильно.
Это продолжение обсуждения с @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;
}
Я знаю, что это просто синтаксический сахар и применимо только в .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; }
Доказательство правильности - рассмотрим множество всех натуральных чисел и предположим, что существует непустое множество целых чисел, которые не являются нечетными. Поскольку положительные целые числа хорошо упорядочены, будет наименьшее нечетное число, которое само по себе довольно странно, поэтому ясно, что число не может быть в наборе. Поэтому этот набор не может быть не пустым. Повторите эти действия для отрицательных целых чисел, за исключением того, что ищите наибольшее нечетное число.
Как сообщают некоторые люди, существует множество способов сделать это. По данным этого сайта , самый быстрый способ - это оператор модуля:
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 или почему они его используют?
Чтобы дать более подробную информацию о методе побитового оператора для тех из нас, кто не делал много булевой алгебры во время наших исследований, вот объяснение. Возможно, не очень полезен для ОП, но мне хотелось прояснить, почему работает NUMBER & 1.
Обратите внимание, что, как кто-то ответил выше, способ представления отрицательных чисел может остановить этот метод. Фактически он может даже нарушить метод оператора по модулю, поскольку каждый язык может отличаться в том, как он работает с отрицательными операндами.
Однако, если вы знаете, что NUMBER всегда будет положительным, это работает хорошо.
Как Туни выше указал, что важна только последняя цифра в двоичном коде (и динарий).
Логический логический элемент И требует, чтобы оба входа были равны 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
), но если вы хотите быть читабельными, используйте modulo 2 ( x % 2
)
%
. Если вы хотите, чтобы он был читабельным, используйте %
. Хм, я вижу образец здесь.
Проверка четного или нечетного является простой задачей.
Мы знаем, что любое число, точно делимое на 2, является четным числом, нечетным.
Нам просто нужно проверить делимость любого числа и для проверки делимости мы используем %
оператор
Проверка четного нечетного с помощью if else
if(num%2 ==0)
{
printf("Even");
}
else
{
printf("Odd");
}
C программа для проверки четного или нечетного использования, если еще
Использование условного / троичного оператора
(num%2 ==0) printf("Even") : printf("Odd");
C программа для проверки четного или нечетного с использованием условного оператора .
Использование побитового оператора
if(num & 1)
{
printf("Odd");
}
else
{
printf("Even");
}
!(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
Когда мы сравниваем 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 обозначает ложь, а T - истину.
Он сравнивает только самый правый бит, если они оба верны. Таким образом, автомагический
7 & 1
является T Рит.
Просто измените n & 1
значение n & 2
2 0010
на двоичное и т. Д.
Я предлагаю использовать шестнадцатеричное обозначение, если вы новичок в побитовых операциях
return n & 1;
>> return n & 0x01;
.