2011-01-21 8 views
11

~ &^| + << >> единственные операции я могу использоватьРеализация логического отрицания только поразрядными операторов (за исключением!)

Прежде чем я продолжу, это домашнее задание вопрос, я застрял на этом в течение очень долгого времени.

Мой оригинальный подход: я думал, что! X можно сделать с дополнением двух и сделать что-то с его аддитивным обратным. Я знаю, что xor, вероятно, здесь, но я действительно в недоумении, как подойти к этому.

Для справки: Я также не могу использовать условные обозначения, петли, == и т. Д., Только функции (побитовые), упомянутые выше.

Например:

!0 = 1 
!1 = 0 
!anything besides 0 = 0 
+2

Вы действительно хотите, чтобы оценить непосредственно 1 и 0, или просто логическим истинным и ложным? то есть '~ 0' приемлема как логическая истина? –

+1

Примечание: '+' не является побитовым оператором. –

+2

Этот вид упражнений по своей сути бессмыслен, потому что любое * использование * результата требует условного сравнения, которое по существу сравнивается с нулем. Мой ответ будет «if (var); else {/ * ваш код здесь * /} ' –

ответ

0

Если предположить, например, 8-разрядный беззнаковый тип:

~(((x >> 0) & 1) 
| ((x >> 1) & 1) 
| ((x >> 2) & 1) 
... 
| ((x >> 7) & 1)) & 1 
+0

Нам нужно работать со знаками целых чисел. – Jay

+0

@Jay - Сделайте листинг как '* (unsigned *) & i' –

1

Следующий код копирует любой 1 бит во все позиции. Это отображает все ненулевые значения в 0xFFFFFFFF == -1, оставляя 0 по адресу 0. Затем он добавляет 1, отображая -1 в 0 и 0 в 1.

x = x | x << 1 | x >> 1 
x = x | x << 2 | x >> 2 
x = x | x << 4 | x >> 4 
x = x | x << 8 | x >> 8 
x = x | x << 16 | x >> 16 

x = x + 1 
+1

Вместо' x + 1' вы могли бы сделать '~ x'. –

+1

@Chris Lutz: Это отображает от 0 до -1, а не обязательно 1. – wnoise

-3

Вы можете просто сделать ~ х & 1, потому что она дает 1 при 0 и 0 для всех остальных

+3

~ 2 & 1 == 1 ... –

7

Предполагая 32-битовое беззнаковое INT:

(((x>>1) | (x&1)) + ~0U) >> 31 

должен сделать трюк

+2

Nice. Преобразует все числа, кроме 0, в «положительные», а затем вычитает 1, что делает только 0 отрицательным, а затем извлекает знаковый бит. – wnoise

+0

@wnoise: спасибо. Я не мог понять его. – BlackBear

1

Для 32-битного целого числа со знаком x

// Set the bottom bit if any bit set. 
x |= x >> 1; 
x |= x >> 2; 
x |= x >> 4; 
x |= x >> 8; 
x |= x >> 16; 

x ^= 1; // Toggle the bottom bit - now 0 if any bit set. 
x &= 1; // Clear the unwanted bits to leave 0 or 1. 
2

Предполагая, что x подписан, необходимо вернуть 0 для любого числа, не равного нулю, и 1 для нуля.

Правая смена знака с целым числом обычно является арифметическим сдвигом в большинстве реализаций (например, бит знака копируется). Поэтому правый сдвиг x на 31 и его отрицание на 31. Один из этих двух будет отрицательным числом, и поэтому сдвиг вправо на 31 будет 0xFFFFFFFF (конечно, если x = 0, то правый сдвиг будет производить 0x0, что вы хотите) , Вы не знаете, является ли x или его отрицание отрицательным числом, поэтому просто «или» вместе, и вы получите то, что хотите. Затем добавьте 1 и ваш товар.

реализация:

int bang(int x) { 
    return ((x >> 31) | ((~x + 1) >> 31)) + 1; 
} 
+0

Я думаю, вы должны свести на нет, а не добавлять его. А именно, '~ ((x >> 31) | ((~ x + 1) >> 31))'. –

+0

Собственно, нет. Добавление 1 верно. Я забыл, что '>>' сдвиги являются арифметическими в C, а не логическими. Таким образом, '>> 31'-ing' 10 ... 00' будет выдавать '11 ... 11', а не' 00 ... 01'. –

 Смежные вопросы

  • Нет связанных вопросов^_^