题
我在一个小的硬件接口项目基础上,威尔曼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#?
解决方案
我想你会需要它翻译成这样:
i & 1 == 1
i & 2 == 2
i & 4 == 4
...等 这是使用位AND运算符。
当使用位AND运算符,该操作者将比较两个给定的值的二进制表示,并返回其中只有那些比特被设置为二进制值,其也可在两个操作数设置。
例如,当你这样做:
2 2
它会做到这一点:
0010 & 0010
和这将导致:
0010
0010
&----
0010
然后,如果你比较这个结果与图2(0010),它将ofcourse返回true。
其他提示
这是做一个位与 ,而不是一个逻辑AND。
每个那些的基本决定在i
单个位是否被设置,例如:
5 AND 4 = 4
5 AND 2 = 0
5 AND 1 = 1
(因为5 =二进制101,和图4,2和1分别是二进制100,010和001的十进制值。)
只需补充: 这就是所谓的bitmasking http://en.wikipedia.org/wiki/Mask_(computing)
一个布尔值仅需要1个比特。在执行大多数编程语言,一个布尔值需要比单一点。在PC这不会是一个很大的浪费,但嵌入式系统通常具有非常有限的内存空间,因此浪费实在是显著。 要节省空间下,该布尔值挤在一起,这样一来一个布尔变量只占用1比特。
您可以把它看作是做这样的事情的数组索引操作后,用一个字节(= 8位)变得像8个布尔变量的阵列,所以也许这就是你的答案:使用数组的布尔值。
在二进制e.g想到此。
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#使用 BitArray类以直接索引各个位。
要设置单个位的 I 的是直接的:
b |= 1 << i;
要复位单个位的 I 的是多一点别扭:
b &= ~(1 << i);
注意的是,位运算符和移位运算符倾向于促进一切int
其可能会意外地需要铸件。
如所述的,这是一个按位AND,而不是一个逻辑AND。我也看到,这已经在我之前好几次说,但国际海事组织的解释是不那么容易理解了。
我喜欢把这样的:
写了二进制数下彼此(这里我做5和1):
101
001
现在,我们需要把它变成一个二进制数,所有从第1号1成的,这也是第二个被转移,那就是 - 在这种情况下:
001
在这种情况下,我们看到它给出了相同的数量第二数目,其中,该操作(在VB)返回true。让我们看一下其它实施例(使用5为ⅰ):
(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更好更有意义。