这为什么有效? (在c ++中找到奇数)

时间:2009-09-22 18:40:49

标签: c++ bitmask

for (unsigned int i = 1; i <= 100; i++) {
    if (i & 0x00000001) {
        std::cout << i<<",";
    }
}

为什么(以及如何):if( i & 0x00000001 )找出奇数?

9 个答案:

答案 0 :(得分:22)

0x00000001是二进制的1,尽管它是用十六进制(base-16)表示法编写的。这是0x部分。

&是按位'AND'运算符,用于执行二进制数字(位)操作。

i & 1将i的所有二进制数字转换为零,除了最后一位。

将得到的1位数转换为布尔值,直接用if语句进行评估。

下图显示了i的最后16位二进制数字,以及它们会发生什么。

i:   i in binary:        i & 1 in binary:    convert to boolean
---- ------------------- ------------------- ---------------------
1    0000000000000001    0000000000000001    true
2    0000000000000010    0000000000000000    false
3    0000000000000011    0000000000000001    true
4    0000000000000100    0000000000000000    false
5    0000000000000101    0000000000000001    true
6    0000000000000110    0000000000000000    false
7    0000000000000111    0000000000000001    true
8    0000000000001000    0000000000000000    false
...  ...                 ...                 ...
99   0000000001100011    0000000000000001    true
100  0000000001100100    0000000000000000    false

答案 1 :(得分:21)

它使用按位“和”运算符来屏蔽除最后一位之外的所有内容。如果最后一位是1,则该数字是奇数。那是否足够解释?

答案 2 :(得分:13)

当我们查看基数为10的数字时,很容易判断一个数字是否可以被10整除:它在最后一个位置有一个0。上面的代码也会查看最后一个位置的数字,但是在基数2中。如果它不为零,则数字可被2整除。

答案 3 :(得分:10)

它掩盖了最后一点。如果你看一个数字(...,256,128,64,32,16,8,4,2和1)的二进制表示中的每个地方,你会注意到只有一个地方是奇数。无论位是置位还是清零(零均为偶数),所有其余位置都具有偶数值。添加偶数将始终给出偶数。只有最后一个位置才能确定数字的奇偶校验。 i & &0x00000001部分只是隔离了最后一个地方。

答案 4 :(得分:3)

你正在做逐位比较。 if bit0 AND bit0都是1,那么答案的bit0 = 1。

看到&amp; 0x00000001为1,任何带该位的数字都是奇数。

0x00000001 = 1
0x00000010 = 2
0x00000011 = 3
etc.

所以,如果你按位进行AND

00000001 AND 
00000001 = 
00000001 (same as true)

00000010 AND 
00000001 = 
00000000 (same as false)

00000011 AND 
00000001 = 
00000001 (same as true)

etc

答案 5 :(得分:3)

奇数是形式的所有数字(2 * n + 1),其中n是任何整数(-2,-1,0,1 ....)。所以要找到一个奇数,你必须看看你正在使用的整数是否有'+1'。当存储为无符号整数时,数字可以表示为2:2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 4等的幂的总和。无符号整数的二进制版本看起来像真值图各种各样:对于每个地方,二进制数中都有一个“1”,将该数字加到该数字上。因此,如果从无符号整数的二进制表示中的最右边的数字开始并向左移动,则每个数字表示2的幂。如果数字为1,那么您将2的幂加到运行总和以及到达二进制数的末尾。

因此:10001110b可以通过将2的幂相加来转换为整数:

最右边:2 ^ 1 + 2 ^ 2 + 2 ^ 3 + 2 ^ 7:最左边= 141

诀窍是最右边的数字代表2 ^ 0。这始终是1.所有其他数字代表偶数。所以,就奇数而言,你必须找到'+1'。这对应于最右边的数字。所有其他数字代表'2 * n'形式的数字。因此,要确定此格式(无符号整数)的数字是否为奇数,您只需要查看最右边的位是否为“1”。

对无符号整数执行的操作是逻辑AND运算。与0的任何AND与0为1,与1的1与1为1.因此,除了表示2 ^ 0(即1)的二进制数字之外,该操作将使无符号整数表示中的所有二进制数字为0。所以无符号整数二进制表示如果是奇数则会归结为0x00000001,如果是偶数则会归结为0x00000000。

注意:当我写0x00000000时,'0x'表示它是十六进制格式。每个“0”代表四位。所以对于00000000b,0x00是十六进制的 以二进制写出,在对无符号整数进行AND运算后得到的无符号整数二进制表示为:

00000000000000000000000000000000b == 0 和 00000000000000000000000000000001b == 1

答案 6 :(得分:2)

在我说出以下内容之前,我首先会说我几乎总是使用位测试来确定int是奇数还是偶数。

但是,严格来说,您应该使用(i % 2)((i % 2) != 0)来确定i是否为奇数。无论负数的表示如何,这都会起作用,而在一个补码机器上(-3&amp; 0x01)将返回零(一个错误的结果),即使它显然很奇怪。

我意识到,使用除了两个补码以外的东西代表负数的机器人现在非常非常罕见,但是现在编译器也会普遍地将(i % 2)编译成一个小测试。请记住,我通常不会在这里遵循自己的建议,因此这可能表明了这一建议的真正价值。

答案 7 :(得分:0)

按位AND运算符跟随每个位的真值表:
0&amp; 0 = 0
0&amp; 1 = 0
1&amp; 0 = 0
1&amp; 1 = 1

由于计算机使用基数为2的数字,每个位代表两个值的幂(1,2,4,8,16 ..),因此最低有效位代表唯一的奇数,无论大小值是,无论是签名还是未签名。由于仅在两个操作数都设置了该位时才设置结果位,当且仅当数字为奇数时,结果才为真。

例: 0b1110101 1 =
(1 * 2 ^ 0) +(1 * 2 ^ 1)+(0 * 2 ^ 2)+(1 * 2 ^ 3)+
(0 * 2 ^ 4)+(1 * 2 ^ 5)+(1 * 2 ^ 6)+(1 * 2 ^ 7)=
1 + 2 + 0 + 8 + 0 + 32 + 64 + 128 = 235
如果没有设置最低有效位,则该值将为234,因此为偶数。

答案 8 :(得分:0)

例如我们如何制作二元等价

8 4 2 1

0 0 0 0 = 0

0 0 0 1 = 1

0 0 1 0 = 2

0 0 1 1 = 3

所以你可以看到任何奇怪的没有。 LSB始终设置,同样检查:)

我希望我的回答很清楚