9

我正在开发一个基于 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#?

4

10 回答 10

19

这是按位与,而不是逻辑与。

其中每一个基本上确定是否i设置了单个位,例如:

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

(因为 5 = 二进制 101,而 4、2 和 1 分别是二进制 100、010 和 001 的十进制值。)

于 2009-04-27T08:57:51.040 回答
15

我认为您必须将其翻译为:

i & 1 == 1

i & 2 == 2

i & 4 == 4 

等等...这是使用按位与运算符。

当您使用按位 AND 运算符时,此运算符将比较两个给定值的二进制表示,并返回一个二进制值,其中仅设置了那些位,这些位也在两个操作数中设置。

例如,当您这样做时:

2 & 2

它会这样做:

0010 & 0010

这将导致:

 0010
 0010
&----
 0010

然后,如果将此结果与 2 (0010) 进行比较,它当然会返回 true。

于 2009-04-27T08:58:27.217 回答
3

只是补充一下:它被称为位掩码 http://en.wikipedia.org/wiki/Mask_(computing)

布尔值只需要 1 位。在大多数编程语言的实现中,布尔值需要不止一个位。在PC中这不会造成很大的浪费,但是嵌入式系统通常具有非常有限的内存空间,因此浪费确实很大。为了节省空间,布尔值被打包在一起,这样一个布尔变量只占用 1 位。

您可以将其视为执行数组索引操作之类的操作,其中一个字节(= 8 位)变成了一个由 8 个布尔变量组成的数组,所以也许这就是您的答案:使用一个布尔数组。

于 2009-04-27T09:15:23.883 回答
1

用二进制考虑这个,例如

10101010

AND

00000010

产量00000010

即不为零。现在如果第一个值是

10101000

你会得到

00000000

即零。

请注意进一步的划分,以将所有内容减少到 1 或 0。

于 2009-04-27T08:58:18.090 回答
1

(i and 16) / 16提取第 5 位的值(1 或 0)。

1xxxx and 16 = 16 / 16 = 1
0xxxx and 16 = 0 / 16 = 0
于 2009-04-27T08:59:00.333 回答
1

And运算符执行“...对两个数值表达式的按位连接”,映射到 '|' 在 C# 中。'` 是一个整数除法,在 C# 中等效的是/,前提是两个操作数都是整数类型。

于 2009-04-27T08:59:49.723 回答
1

常数是掩码(以二进制形式考虑它们)。所以代码所做的是对字节和掩码应用按位与运算符并除以数字,以获得位。

例如:

xxxxxxxx & 00000100 = 00000x000
if x == 1
    00000x00 / 00000100 = 000000001
else if x == 0
    00000x00 / 00000100 = 000000000
于 2009-04-27T09:05:37.450 回答
1

如前所述,这是按位与,而不是逻辑与。我确实看到这在我之前已经说过很多次了,但是 IMO 的解释并不那么容易理解。

我喜欢这样想:

写下彼此的二进制数(这里我在做 5 和 1):

101
001

现在我们需要将其转换为二进制数,其中第一个数字中的所有 1,也就是第二个数字中的所有 1 都被转移,即 - 在这种情况下:

001

在这种情况下,我们看到它给出了与第二个数字相同的数字,其中此操作(在 VB 中)返回 true。让我们看看其他示例(使用 5 as 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;
于 2009-04-27T09:06:23.907 回答
1

在 C# 中,使用BitArray 类直接索引各个位。

要设置单个位i很简单:

b |= 1 << i;

要重置单个位i有点尴尬:

b &= ~(1 << i);

请注意,位运算符和移位运算符都倾向于将int可能意外需要转换的所有内容都提升到。

于 2009-04-27T09:28:55.350 回答
1

我更喜欢在位旋转时使用十六进制表示法(例如 0x10 而不是 16)。当您增加位深度时,它更有意义,因为 0x20000 比 131072 更好。

于 2009-04-27T19:37:38.660 回答