Зачем И два числа, чтобы получить логическое значение? - PullRequest
9 голосов
/ 27 апреля 2009

Я работаю над небольшим проектом Аппаратного интерфейса на плате Velleman k8055.

Пример кода поставляется на VB.Net, и я переписываю его на C #, в основном, чтобы иметь возможность пройтись по коду и разобраться во всем этом.

Одна вещь сбила меня с толку, хотя:

На одном этапе они читают все цифровые входы, а затем устанавливают флажок на основе ответа на считанные цифровые входы (которые возвращаются в виде целого числа), а затем они И это с номером:

i = ReadAllDigital
cbi(1).Checked = (i And 1)
cbi(2).Checked = (i And 2) \ 2
cbi(3).Checked = (i And 4) \ 4
cbi(4).Checked = (i And 8) \ 8
cbi(5).Checked = (i And 16) \ 16

Я давно не занимался цифровыми системами, и я понимаю, что они пытаются сделать, но как это повлияет на И два числа? Разве все, что выше 0, не соответствует истине?

Как бы вы перевели это на C #?

Ответы [ 10 ]

19 голосов
/ 27 апреля 2009

Это делает побитовое И , а не логическое И.

Каждый из них в основном определяет, установлен ли один бит в i, например:

5 AND 4 = 4
5 AND 2 = 0
5 AND 1 = 1

(Поскольку 5 = двоичное 101, а 4, 2 и 1 - десятичные значения двоичного 100, 010 и 001 соответственно.)

15 голосов
/ 27 апреля 2009

Я думаю, вам придется перевести это на:

i & 1 == 1

i & 2 == 2

i & 4 == 4 

... и т.д. Это использует побитовый оператор AND.

Когда вы используете побитовый оператор AND, этот оператор сравнивает двоичное представление двух заданных значений и возвращает двоичное значение, где установлены только те биты, которые также установлены в двух операндах.

Например, когда вы делаете это:

2 & 2

Это сделает это:

0010 & 0010

И это приведет к:

 0010
 0010
&----
 0010

Тогда, если вы сравните этот результат с 2 (0010), он, конечно, вернет true.

3 голосов
/ 27 апреля 2009

Просто добавить: Это называется битмасингом http://en.wikipedia.org/wiki/Mask_(computing)

Для логического значения требуется только 1 бит. В реализации большинства языков программирования логическое значение занимает больше, чем один бит. В ПК это не будет большой тратой, но встроенные системы обычно имеют очень ограниченное пространство памяти, поэтому траты действительно значительны. Для экономии места логические значения упакованы вместе, поэтому логическая переменная занимает всего 1 бит.

Вы можете думать об этом как о чем-то вроде операции индексации массива , когда байт (= 8 бит) становится массивом из 8 логических переменных, так что, возможно, это ваш ответ: используйте массив булевы.

1 голос
/ 27 апреля 2009

Я предпочитаю использовать шестнадцатеричное обозначение, когда бит тиддлинг (например, 0x10 вместо 16). Это имеет больше смысла, поскольку вы увеличиваете свою разрядность, так как 0x20000 лучше, чем 131072.

1 голос
/ 27 апреля 2009

В C # используйте класс BitArray для прямого индексирования отдельных битов.

Чтобы установить отдельный бит i , это просто:

b |= 1 << i;

Сбросить отдельный бит i немного более неудобно:

b &= ~(1 << i);

Имейте в виду, что как побитовые операторы, так и операторы сдвига стремятся преобразовать все в int, что может неожиданно потребовать приведения.

1 голос
/ 27 апреля 2009

Как уже говорилось, это побитовое И, а не логическое И. Я вижу, что это было сказано довольно много раз до меня, но объяснения ИМО не так легко понять.

Мне нравится думать об этом так:

Запишите двоичные числа друг под другом (здесь я делаю 5 и 1):

101
001

Теперь нам нужно превратить это в двоичное число, где все 1 из 1-го числа, которое также во втором, передается, то есть - в данном случае:

001

В этом случае мы видим, что он дает тот же номер, что и 2-й номер, в котором эта операция (в VB) возвращает true. Давайте посмотрим на другие примеры (используя 5 как i):

(5 и 2)

101
010
----
000

(ложь)

(5 и 4)

101
100
---
100

(истина)

(5 и 8)

0101
1000
----
0000

(ложь)

(5 и 16)

00101
10000
-----
00000

(ложь)

РЕДАКТИРОВАТЬ: и, очевидно, я скучаю по всей сути вопроса - вот перевод на C #:

cbi[1].Checked = i & 1 == 1;
cbi[2].Checked = i & 2 == 2;
cbi[3].Checked = i & 4 == 4;
cbi[4].Checked = i & 8 == 8;
cbi[5].Checked = i & 16 == 16;
1 голос
/ 27 апреля 2009

Постоянные числа маски (представьте их в двоичном виде). Таким образом, код применяет оператор побитовое И к байту и маске и делит их на число, чтобы получить бит.

Например:

xxxxxxxx & 00000100 = 00000x000
if x == 1
    00000x00 / 00000100 = 000000001
else if x == 0
    00000x00 / 00000100 = 000000000
1 голос
/ 27 апреля 2009

И оператор выполняет «... побитовое соединение двух числовых выражений», которое отображается на '|' в C #. '`Является целочисленным делением , и эквивалент в C # равен /, при условии, что оба операнда являются целочисленными типами.

1 голос
/ 27 апреля 2009

(i и 16) / 16 извлекает значение (1 или 0) 5-го бита.

1xxxx and 16 = 16 / 16 = 1
0xxxx and 16 = 0 / 16 = 0
1 голос
/ 27 апреля 2009

Думайте об этом в двоичном виде, например

10101010

AND

00000010

урожайность 00000010

т.е. не ноль. Теперь, если первое значение было

10101000

вы получите

00000000

т.е. ноль.

Обратите внимание на дальнейшее деление, чтобы уменьшить все до 1 или 0.

...