Почему И два числа, чтобы получить логическое значение?

StackOverflow https://stackoverflow.com/questions/792708

  •  16-09-2019
  •  | 
  •  

Вопрос

Я работаю над небольшим проектом аппаратного интерфейса, основанным на плате 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

Я давно не занимался цифровыми системами и понимаю, что они пытаются сделать, но какой эффект это окажет на AND two numbers?Разве все, что выше 0, не равно true?

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

Это было полезно?

Решение

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

i & 1 == 1

i & 2 == 2

i & 4 == 4 

и т.д...При этом используется побитовый оператор AND .

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

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

2 & 2

Он сделает это:

0010 & 0010

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

 0010
 0010
&----
 0010

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

Другие советы

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

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

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

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

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

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

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

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

10101010

AND

00000010

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

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

10101000

вы бы получили

00000000

т. е.ноль.

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

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

1xxxx and 16 = 16 / 16 = 1
0xxxx and 16 = 0 / 16 = 0

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

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

Например:

xxxxxxxx & 00000100 = 00000x000
if x == 1
    00000x00 / 00000100 = 000000001
else if x == 0
    00000x00 / 00000100 = 000000000

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

Для установки отдельного бита i это прямолинейно:

b |= 1 << i;

Для сброса отдельного бита i это немного более неловко:

b &= ~(1 << i);

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

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

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

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

101
001

Теперь нам нужно преобразовать это в двоичное число, где будут перенесены все единицы из 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;

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top