布尔“(number&1)== 0”是什么意思?


79

在CodeReview上,我发布了一段有效的代码,并要求改进的技巧。我得到的是使用一种布尔方法来检查ArrayList是否具有偶数个索引(这是必需的)。这是建议的代码:

private static boolean isEven(int number)
{
    return (number & 1) == 0;
}

因为我已经困扰了该特定用户很多帮助,所以我决定是时候该困扰SO社区了!我真的不明白这是如何工作的。调用该方法,并将ArrayList的大小作为参数(即ArrayList有十个元素,数字= 10)。

我知道有一个&数字与1进行比较,但此后我迷路了。

我的阅读方式是,如果number == 0和,则返回true 1 == 0。我知道第一个是不正确的,而后者显然是没有意义的。有人可以帮我吗?

编辑:我可能应该补充一点,代码可以正常工作,以防万一。


2
有人知道谁将此链接链接到其他帖子(与该内容无关)吗?我可以以某种方式删除它吗?
Andrew Martin

1
该死的,这真的很聪明!
cauon

2
这是在Twitter上的特色。
乔纳森·莱因哈特


1
@GrijeshChauhan您能详细说明一下这比number % 2 == 0??快吗?
Vrushank

Answers:


114

请记住,“&”是按位运算。您可能已经意识到了这一点,但是根据您提出问题的方式,这对我来说并不十分清楚。

就是说,理论上的想法是您有一个int,可以用一些1和0的序列以位表示。例如:

...10110110

在二进制中,因为它是基数2,所以当数字的按位版本以0结尾时,它是偶数,而当以1结尾时,它是奇数。

因此,对以上内容按位与1是:

...10110110 & ...00000001

当然,它是0,所以您可以说原始输入是偶数。

或者,考虑一个奇数。例如,将1加到上面的值上。然后

...10110111 & ...00000001

等于1,因此不等于零。瞧


13
谢谢-您的解释很清楚。再加上任何以“ Voila”结尾的答案都应该得到赞扬。
安德鲁·马丁

1
可能还应该知道此答案中的负数。
艾文·黄

3
另外,我可能会修改此答案,以包括n%k == n&(k-1)对所有k这些都是2的正幂的事实。这也许不是提问者所要求的,但要知道这是一件方便的事情。
蓬松的

1
@fluffy并不是说这行不通,但是并不是每个人都知道两个的补码。
Alvin Wong

1
@fluffy在该表达式中不应该存在alog2^某处吗?
纳文

67

您可以通过二进制表示形式的最后一位来确定数字是偶数还是奇数:

1 -> 00000000000000000000000000000001 (odd)
2 -> 00000000000000000000000000000010 (even)
3 -> 00000000000000000000000000000011 (odd)
4 -> 00000000000000000000000000000100 (even)
5 -> 00000000000000000000000000000101 (odd)
6 -> 00000000000000000000000000000110 (even)
7 -> 00000000000000000000000000000111 (odd)
8 -> 00000000000000000000000000001000 (even)

& 两个整数之间是按位AND运算符:

0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1

因此,如果(number & 1) == 0true,则表示number为偶数。


假设number == 6,然后:

6 -> 00000000000000000000000000000110 (even)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

0 -> 00000000000000000000000000000000

以及何时number == 7

7 -> 00000000000000000000000000000111 (odd)

     &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&

1 -> 00000000000000000000000000000001

-------------------------------------

1 -> 00000000000000000000000000000001

18

&是按位AND运算符。&&是逻辑AND运算符

对于二进制,如果将数字位设置为1(即1),则该数字为奇数。

在二进制中,如果数字位为零,则数字为偶数。

(number & 1) 是对数字位的按位与测试。

完成此操作的另一种方法(可能效率较低,但更容易理解)是使用模运算符%

private static boolean isEven(int number)
{
    if (number < 0)
       throw new ArgumentOutOfRangeException();

    return (number % 2) == 0;
}

2
&也是逻辑与。&&短路而&没有。
Steve Kuo

5
number % 2是不一样的number & 1,如果number是负的。
dan04

4
如果通过负数长度,那么您会遇到更大的问题!;)
Mitch Wheat

4
@RyanAmos“迭代每一位?” 按位与是我见过的每个CPU中的单个操作-它是并行执行的最简单的操作之一。
蓬松的

2
@MitchWheat没有理由扔在number < 0壳体-而奇数负数MOD 2为-1,一个连一个模2仍为0
蓬松

8

该表达式的意思是“整数表示偶数”。

原因如下:十进制的二进制表示形式100000000001。所有奇数都1以二进制结尾(这很容易验证:假设数字的二进制表示形式不以结尾1;然后它由非零的2的幂组成,始终为偶数)。当您AND使用奇数执行二进制操作时,结果为1; 当您AND使用偶数进行二进制运算时,结果为0

在优化器较差或根本不存在时,这曾经是确定奇/偶数倒数的首选方法,而%运算符需要的次数是&运算符所花费的二十倍。如今,如果您这样做的话number % 2 == 0,编译器很可能会生成与执行一样快的代码(number & 1) == 0


5

单一&表示按位and运算符而不是比较

因此,此代码检查是否设置了第一个bit(最低有效/最右),以指示该数字是否正确odd。因为所有奇数都将以1最低有效位结尾,例如xxxxxxx1


请注意,如果您想避免诸如&andf(x) & g(x)
Navin

4

&是按位AND操作。

对于数字= 8:

  1000
  0001
& ----
  0000

结果就是这样(8 & 1) == 0。所有偶数都是这种情况,因为它们是2的倍数,并且从右边开始的第一个二进制数字始终为0。1的二进制值是1,前导0,因此当我们AND使用偶数时,就剩下与0。


3

&Java中操作是按位与操作。基本上,(number & 1)在和之间执行按位number1。结果是0还是1,具体取决于它是偶数还是奇数。然后将结果与0进行比较,以确定其是否为偶数。

这是描述按位运算页面


3

它正在执行二进制运算,并与1相对,如果未设置最低有效位,则返回0

举个例子

00001010(10)

00000001(1)

===========

00000000(0)


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.