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

Замена "==" побитовыми операторами

Используя только побитовые операторы (|, &, ~, ^, → , < <) и другие базовые операторы, такие как +, - и и, можно заменить "==" ниже?

int equal(int x, int y) {
    return x == y;
}
4b9b3361

Ответ 1

Два числа равны, если между ними нет разницы:

int equal(int x, int y){
   return !(x-y);
}

Ответ 2

Помните, что XOR точно такой же, как NOT EQUALS и XNOR точно такой же, как EQUALS. Итак, следующее даст вам именно то, что вы хотите:

return !(x ^ y);

Ответ 3

Оператор C ! на самом деле просто сокращен для != 0, поэтому использование его кажется очень близким к обману:)

Здесь я беру только использование побитовых операций, предполагая 32-битную двухкомпонентную машину с арифметическими сдвигами вправо (технически, в С арифметических сдвигах вправо undefined, но каждый компилятор C, который я когда-либо видел на машине с двумя дополнениями поддерживает это правильно):

int t = (x - y) | (y - x); // <0 iff x != y, 0 otherwise
t >>= 31; // -1 iff x != y, 0 otherwise
return 1 + t; // 0 iff x != y, 1 otherwise

Тем не менее, у реальных компиляторов нет этой проблемы. Фактическое оборудование фактически имеет прямую поддержку для сравнения. Детали зависят от архитектуры, но есть две основные модели:

  • Коды условий, возвращаемые для арифметических операций (например, x86 и ARM делают это). В этом случае обычно используется команда "сравнения", которая вычитает два значения, не записывает обратно в регистр целочисленных чисел, а устанавливает код условия/флаги на основе результата.
  • Более RISC-подобные платформы обычно имеют прямые "ветки, если они равны" и "ветвь, если меньше" операндов, которые выполняют сравнение и ветвь на основе результата. Это в основном эквивалентно C-коду

    if (a == b) goto label;
    

    или

    if (a < b) goto label;
    

    все в одной машинной инструкции.

Ответ 4

Этот пример аналогичен вычитанию, но более ясен, как некоторые архитектуры регистрируют сравнение (например, ARM, я полагаю).

return !(1 + ~x + y);

1 означает входной бит в ALU. Одно число x побито дополнено. Принимая дополнение и добавление 1, выдает два дополнения числа (x становится -x), а затем добавляется к другому числу, чтобы получить разницу для определения равенства.

Итак, если оба числа равны, вы получаете -x + x => 0.

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

Ответ 5

Так как XOR совпадает с (! =), значит, (x ^ y) вернет 0 только для равных значений. Я считаю, что это разумно, использует бит-мудрый оператор и работает.

int notEqual(int x, int y){
        return (x ^ y);
}

Ответ 6

My Take this this

int equal(int x, int y){
   if((x & ~y) == 0)
       return 1;
   else
       return 0; 
}

Объяснение: Если x == y, то x & ~y получает значение 0 return 1, else возвращает 0 как x!=y.

Edit1: The above is equivalent to 

int equal(int x, int y){
    return !(x & ~y) ; // returns 1 if equal , 0 otherwise. 
}

Вышеприведенный код терпит неудачу в некоторых случаях, когда самый старший бит равен 1. Решение состоит в том, чтобы добавить 1. Правильный ответ:

return !(x & (~y +1) );