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

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

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

我知道单个&可以同时进行数字和1的比较,但是在那之后我迷路了。

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

编辑:我可能应该补充一点,如果有人想知道的话,代码确实可以工作。

@ Eng.Fouad:真令人气愤的是,我在大学初期就研究了这个,却忘记了所有。现在看来是如此明显!

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

该死的,这真的很聪明!

比number % 2更快,以检查最后一位是否为偶数

@cauon:完全是我的想法。我绝对不能想到这一点!

这是在Twitter上的特色。

@JonathonReinhart:你什么意思?

@AndrewMartin twitter.com/StackExchange/status/302768803719286785

@BurhanAli:太好了!

您误读了该表达式。看一下括号在哪里。

@EJP:是的,昨天整理完了,谢谢。

尽管该代码有效,IMO,但您不得不在SO上发布有关该代码的事实表明该代码缺乏可读性。在这种情况下,使用模量运算符(%)可能会有意义,尽管我可能会遗漏一些东西。

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

@Vrushank读取此按位运算的速度比除法快得多,比乘法快几倍

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

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

...10110110

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

因此,对上面的代码按1进行"与"运算是:

...10110110 & ...00000001

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

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

...10110111 & ...00000001

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

谢谢-您的解释很清楚。再加上任何以Voila结尾的答案都应该得到赞扬。

可能还应该知道此答案中的负数。

@AlvinWong负数也起作用。 -1 = 111...11111。

同样,Id可能会修改此答案,以包含所有k的事实变量,即正整数2的k。这也许不是问问者所要的,而是要知道的一个方便的事情。

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

@fluffy应该在该表达式中某处不存在log或2^吗?

请注意,严格来说,在带符号的int上使用像&这样的二进制运算符是实现定义的(因为它取决于带符号的int的内部表示,这是实现定义的)。实际上,所有现代C实现都使用二进制补码,因此,要点很重要。见stackoverflow.com/a/1161712/43681

@AlvinWong:对于我们的作业,我们只处理大于0的正数。赛跑者主类内置了catch,以防止接受小于或等于0的任何值,所以这不是问题。好点!

@Navin Nope。您也可以将其写为(n%pow(2,k))==n&(pow(2,k)-1),或者更有效地写为n%(1<== n&((1 << k)-1)`,但这只是一种不太易理解的说法,即等价是针对2。

@AlvinWong为什么他们必须知道2s补码?

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

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) == 0是true,则意味着number是偶数。
假设number == 6,则:
6 -> 00000000000000000000000000000110 (even)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1 -> 00000000000000000000000000000001
-------------------------------------
0 -> 00000000000000000000000000000000
以及number == 7时:
7 -> 00000000000000000000000000000111 (odd)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
1 -> 00000000000000000000000000000001
-------------------------------------
1 -> 00000000000000000000000000000001
&是按位与运算符。 &&是逻辑AND运算符
以二进制形式,如果数字位被设置(即1),则数字为奇数。
在二进制中,如果数字位为零,则数字为偶数。
(number & 1)是对数字位的按位与测试。
执行此操作的另一种方法(可能效率较低,但更容易理解)是使用模运算符%:
private static boolean isEven(int number)
{
if (number < 0)
throw new ArgumentOutOfRangeException();
return (number % 2) == 0;
}

我会明白的,你明白了。老实说,我每天都会学习有关Java的知识。没有人指出,这是永远不会得到的。

我倾向于专门使用它。在大多数情况下,性能都要明确。

我无法想象这会慢得多,如果有的话。有人对此有任何信息吗?

我确实说过了。希望优化抖动将做得很好。

假设任何一半不错的窥视孔优化编译器都将看到%2并转换为&1,除非这已被证明是瓶颈,否则运行时差异可以忽略不计

&也是逻辑与。 &&短路,而&则不短路。

如果number为负,则number % 2与number & 1不同。

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

我很好奇Java编译器是否对此进行了优化。 @AndrewMartin会慢很多。对于&,您只需迭代每个位并进行比较。 %必须做更复杂的划分。

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

@MitchWheat没有理由抛出number < 0情况-尽管奇数负数mod 2为-1,偶数mod 2仍为0。

为什么对负参数使用IllegalArgument?他们可能甚至

我应该明确指出,该方法只能接受大于0的正数(Runner类中有它的用法)

如果这样做的效率较低,则应该购买可以进行适当优化的新处理器:即使Java JIT没有对此进行优化,处理器也绝对可以。

Downvoter:请发表评论。

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

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

在优化器较差或根本不存在的情况下,这曾经是确定奇/偶返回的首选方法,%运算符所需的循环次数是&运算符的二十倍。这些天,如果您执行number % 2 == 0,则编译器可能会生成与(number & 1) == 0一样快的代码。

单个&表示按位AND运算符,不进行比较

因此,此代码检查是否设置了第一个bit(最低有效/最右),这表明数字是否为odd;因为所有奇数的最低有效位都以1结尾,例如xxxxxxx1

请注意,如果要避免像f(x) & g(x)这样的表达式产生副作用,可以将单个&用作逻辑and

&是按位AND操作。

对于数字= 8:

1000
0001
& ----
0000

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

这是按位&(AND)运算符的逻辑设计概念。

返回(2&1);表示将值转换为按位数字并比较(AND)功能并返回值。

首选此链接http://www.roseindia.net/java/master-java/java-bitwise-and.shtml

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

举个例子

00001010(10)
00000001(1)
===========
00000000(0)
and不是

哎呀,纠正了

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

这是描述按位操作的页面。