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

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

4

9 回答 9

23

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

&是按位“与”运算符,用于进行二进制数字(位)操作。

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
于 2009-09-22T18:58:02.450 回答
21

它使用按位“与”运算符来屏蔽除最后一位以外的所有内容。如果最后一位为 1,则该数为奇数。解释够了吗?

于 2009-09-22T18:42:21.247 回答
13

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

于 2009-09-22T18:47:08.507 回答
10

它掩盖了最后一点。如果您查看数字的二进制表示中的每个位置(...、256、128、64、32、16、8、4、2 和 1),您会注意到只有一个位置是奇数。无论这些位是设置还是清除,所有其余位置都具有偶数值(零为偶数)。加上偶数总是会得到偶数。只有最后一个的位置决定了数字的奇偶性。该i & &0x00000001部分只是隔离了最后一个位置。

于 2009-09-22T18:48:46.093 回答
3

您正在进行按位比较。如果 bit0 AND bit0 均为 1,则答案的 bit0 = 1。

看到 &0x00000001 是 1,任何带有这个位的数字都是奇数。

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

所以,如果你做一个按位与

00000001 AND 
00000001 = 
00000001 (same as true)

00000010 AND 
00000001 = 
00000000 (same as false)

00000011 AND 
00000001 = 
00000001 (same as true)

etc
于 2009-09-22T18:49:47.847 回答
3

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

因此: 10001110b 可以通过对两个的幂求和转换为整数:

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

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

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

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

000000000000000000000000000000000b == 0 和 00000000000000000000000000000001b == 1

于 2009-09-22T19:04:01.640 回答
2

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

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

我意识到现在使用二进制补码以外的东西来表示负数的机器非常非常罕见,但现在的编译器(i % 2)无论如何都会普遍编译以进行一点测试也是事实。请记住,我通常不会在这里遵循自己的建议,因此这可能表明该建议的真正价值。

于 2009-09-22T21:39:45.757 回答
0

按位与运算符对每一位都遵循这个真值表:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

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,因此是偶数。

于 2009-09-23T05:24:20.233 回答
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 总是设置的,你也检查一下 :)

我希望我的回答很清楚

于 2009-09-23T07:28:19.530 回答