Подтвердить что ты не робот

Поиск того, являются ли подписанное и целое число без знака четными или нечетными

У меня есть int m и unsigned int j и вы хотите определить, являются ли они четными или нечетными.

В прошлом я использовал

if((int(j)+m)%2)

чтобы поймать случай, что только один нечетный. Но меня беспокоит кастинг int, который неправильно меняет нечетную четность j.

У любого из них возникают проблемы?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

Я знаю, что

if(j%2!=m%2)

не работает, потому что "m% 2" будет производить -1, когда m отрицательный, который всегда будет оцениваться как true независимо от того, что имеет значение j%2.

4b9b3361

Ответ 1

Не используйте %. Это проблема, которая вызывает битмаски:

bool same_parity = (i & 0x1) == (j & 0x1);

Это работает независимо от знака i, так как результат этого выражения всегда будет 0 или 1.

Ответ 2

if (1 & (i ^ j))
{
// Getting here if i is even and j is odd
// or if i is odd and j is even
}

^ - это побитовый оператор exclusive-or, который проверяет каждый бит в обоих числах, если они имеют одинаковое значение. Например, если двоичное представление i равно 0101 и j равно 1100, тогда i ^ j будет оцениваться как 1001, так как их первый и последний бит разные, тогда как средние биты являются то же самое.

& - это побитовый оператор and, который проверяет каждый бит в обоих числах, если они оба 1.

Поскольку только последний бит каждого номера определяет, будет ли он четным или нечетным, i ^ j будет оцениваться до ...xxx0, если они являются четными или нечетными, а ...xxx1 в противном случае (x не имеет значения, мы все равно не смотрим на них). Поскольку 1 на самом деле ...0001, 1 & (i ^ j) оценивается как 0, если i и j являются четными или нечетными, а 1 в противном случае.

Это работает на любой комбинации беззнаковых чисел, 2s-дополнения и знака и величины, но не на редком 1s-дополнении, если ровно один отрицательный.

Ответ 3

Добавление двух целых чисел добавляет их четность, поэтому решение просто:

if ( (j + m) % 2 )

Unsigned wraparound не нарушает это свойство, так как оно выполнено по модулю UINT_MAX+1, которое является четным числом.

Это решение не зависит от каких-либо специфических для реализации деталей, таких как представление отрицательных чисел.


Сноска: я изо всех сил пытаюсь понять, почему многие другие ответы усложняют проблему с помощью бит-сдвигов, бит-дополнений, XOR и т.д. и т.д. К сожалению, IMO иногда прославляется в C или С++ сообщества писать хитрый код вместо простого кода.

Ответ 4

При отливке unsigned int, превышающей INT_MAX до int, не гарантируется возврат разумного значения. Результатом является undefined.

Приведение int к unsigned int всегда приводит к определенному поведению - для математики mod 2^k для m k достаточно большой, чтобы каждый положительный int был меньше 2^k.

if((int(j)+m)%2)

должен быть

if((j+unsigned(m))%2)

вместо.

if((j%2)==(unsigned(m)%2))

- самый простой способ увидеть, имеют ли обе одинаковые четности. Переход к unsigned aka mod 2^k будет сохранять четность, а в unsigned %2 корректно возвращает четность (а не отрицательную четность).

Ответ 5

Не слишком умный

У любого из них возникают проблемы?

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

Одна проблема, которую я вижу, - читаемость. Для кого-то другого (или вашего будущего) может быть не очевидно, что он должен делать или что он на самом деле делает.

Вы можете быть более выразительными, потратив несколько дополнительных строк:

#include <cmath>

const bool fooIsEven = foo % 2 == 0;
const bool barIsEven = std::abs(bar) % 2 == 0;
if (fooIsEven == barIsEven)
{
  // ...
}

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

Изменить: Заменено нажатие на вызов на std:: abs

Ответ 6

Это можно упростить:

if(!(j%2)!=!(m%2))
if(bool(j%2)!=bool(j%2))

в

if ((abs(m) % 2) != (j % 2))

обязательно включите math.h

#include <math.h>

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

Преобразование подписанного в unsigned в порядке и определено на C99.

Нашел этот ресурс.

Побитовые операторы также должны работать с компилятором C99, а подписанное с меньшим максимальным значением преобразуется в большее (подписанное без знака).

Ответ 7

Абсолютное значение, чтобы игнорировать его подпись или без знака. Затем манипулируйте, чтобы определить, будет ли разделение на два (тестовая четность) вернуть остаток или нет.

Итак, функция, которая сделает что-то вроде этого для любого числа, будет:

#include <stdlib.h>

int x = -4;
unsigned int = 5;

bool isEven(int number){
   bool result = false;
   int temp = abs(number);
   if (temp % 2 != 1){
       result = true; }
   else {
       result = false; }
   return result;
}

Обратите внимание, что функция возвращает логическое значение - true, если число четное и false, если значение нечетное.

Конечно, возвращаемое по умолчанию значение false будет инициализировано в функции.