[英]why does this work? (finding odd number in c++)
for (unsigned int i = 1; i <= 100; i++) {
if (i & 0x00000001) {
std::cout << i<<",";
}
}
为什么(以及如何): if( i & 0x00000001 )
算出奇数?
0x00000001
是二进制1
,尽管它是用十六进制(base-16)表示法编写的。 这是0x
部分。
&
是一个按位'AND'运算符,用于执行二进制数字(位)操作。
i & 1
将i & 1
所有二进制数字转换为零,除了最后一个。
将得到的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,则该数字是奇数。 那是否足够解释?
当我们查看基数为10的数字时,很容易判断一个数字是否可以被10整除:它在最后一个位置有一个0。 上面的代码也会查看最后一个位置的数字,但是在基数2中。如果它不为零,则该数字不能被2整除。
它掩盖了最后一点。 如果你看一个数字(...,256,128,64,32,16,8,4,2和1)的二进制表示中的每个地方,你会注意到只有一个地方是奇数。 无论位是置位还是清零(零均为偶数),所有其余位置都具有偶数值。 添加偶数将始终给出偶数。 只有最后一个位置才能确定数字的奇偶校验。 i & &0x00000001
部分只是隔离了最后一个位置。
你正在做逐位比较。 if bit0 AND bit0都是1,那么答案的bit0 = 1。
看到&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
奇数是形式的所有数字(2 * n + 1),其中n是任何整数(-2,-1,0,1 ......)。 所以要找到一个奇数,你必须看看你正在使用的整数是否有'+1'。 当存储为无符号整数时,数字可以表示为2:2 ^ 0 + 2 ^ 1 + 2 ^ 2 + 2 ^ 4等的幂的总和。无符号整数的二进制版本看起来像真值图各种各样:对于每个地方,二进制数中都有一个“1”,将该数字加到该数字上。 因此,如果从无符号整数的二进制表示中的最右边的数字开始并向左移动,则每个数字表示2的幂。 如果数字为1,则将2的幂加到运行总和以及到达二进制数的末尾时。
因此:10001110b可以通过对两个幂的求和来转换为整数:
最右边: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和000000000000000000000000000000000001b == 1
在我说下面之前,我首先会说我几乎总是使用位测试来确定int是奇数还是偶数。
但是,严格地说,你应该使用(i % 2)
或((i % 2) != 0)
来确定i
是奇数。 无论负数的表示如何,这都会起作用,而在一个补码机器上(-3和0x01)将返回零(一个错误的结果),即使它显然是奇数。
我意识到,使用除了两个补码以外的东西来代表负数的机器人现在非常非常罕见,但是现在编译器也会普遍编译(i % 2)
到一点测试。 请记住,我通常不会在这里遵循自己的建议,因此这可能表明了这一建议的真正价值。
按位AND运算符跟随每个位的真值表:
0&0 = 0
0&1 = 0
1&0 = 0
1&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 4 2 1
0 0 0 0 = 0
0 0 0 1 = 1
0 0 1 0 = 2
0 0 1 1 = 3
所以你可以看到任何奇怪的没有。 LSB总是设置,同样你检查:)
我希望我的回答很清楚
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.