Используя только побитовые операторы (|, &, ~, ^, → , < <) и другие базовые операторы, такие как +, - и и, можно заменить "==" ниже?
int equal(int x, int y) {
return x == y;
}
Используя только побитовые операторы (|, &, ~, ^, → , < <) и другие базовые операторы, такие как +, - и и, можно заменить "==" ниже?
int equal(int x, int y) {
return x == y;
}
Два числа равны, если между ними нет разницы:
int equal(int x, int y){
return !(x-y);
}
Помните, что XOR
точно такой же, как NOT EQUALS
и XNOR
точно такой же, как EQUALS
. Итак, следующее даст вам именно то, что вы хотите:
return !(x ^ y);
Оператор 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
Тем не менее, у реальных компиляторов нет этой проблемы. Фактическое оборудование фактически имеет прямую поддержку для сравнения. Детали зависят от архитектуры, но есть две основные модели:
Более RISC-подобные платформы обычно имеют прямые "ветки, если они равны" и "ветвь, если меньше" операндов, которые выполняют сравнение и ветвь на основе результата. Это в основном эквивалентно C-коду
if (a == b) goto label;
или
if (a < b) goto label;
все в одной машинной инструкции.
Этот пример аналогичен вычитанию, но более ясен, как некоторые архитектуры регистрируют сравнение (например, ARM, я полагаю).
return !(1 + ~x + y);
1 означает входной бит в ALU. Одно число x
побито дополнено. Принимая дополнение и добавление 1, выдает два дополнения числа (x
становится -x
), а затем добавляется к другому числу, чтобы получить разницу для определения равенства.
Итак, если оба числа равны, вы получаете -x + x => 0
.
(На уровне регистров оператор !
не выполняется, и вы просто проверяете "нулевой бит" кодов условий или флагов, который устанавливается, если операция регистра производит результат с нулем и ясно в противном случае.)
Так как XOR совпадает с (! =), значит, (x ^ y) вернет 0 только для равных значений. Я считаю, что это разумно, использует бит-мудрый оператор и работает.
int notEqual(int x, int y){
return (x ^ y);
}
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) );