for (unsigned int i = 1; i <= 100; i++) {
if (i & 0x00000001) {
std::cout << i<<",";
}
}
为什么(以及如何):if( i & 0x00000001 )
找出奇数?
答案 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始终设置,同样检查:)
我希望我的回答很清楚