Java 位运算符

3
我在Java代码中发现了这段代码,如果有人能解释其中的逻辑,我会非常高兴。
public boolean name(int n) {
   return ((n >> n) & 1L) > 0; 
}

这似乎是一种检查操作,但这段代码会返回什么布尔值呢?是否有替代方案?我正在尽力理解Java中的位操作。

看起来像我会写的谜题。我建议你尝试不同的值并观察它的行为,然后尝试自己解释它。 - Peter Lawrey
这是我会写的那种东西 ;) http://vanillajava.blogspot.co.uk/2012/01/another-shifty-challenge.html - Peter Lawrey
@PeterLawrey 你能为这个找到一个通项公式吗?(即 n 必须为 n = ... 的形式) - assylias
@assylias 我在我的回答中尝试了一下。;) - Peter Lawrey
有上下文吗?这个函数真的被使用了吗? - harold
@PeterLawrey 我也试了一下 ;-) - assylias
4个回答

7

这是一段奇怪的代码。它检测被右移 n % 32 位后的数字 n 是否为奇数。

通过测试的前几个非负数值分别是37(二进制中为100101)、70(二进制中为1000110)和101(二进制中为1100101)。

我怀疑它是否真正按照原始编码者的意图工作 - 它并没有明显地表示任何有用的东西(而且方法名 name 也不太有帮助...)


@assylias:不是的。根据我的测试程序,101也通过了。102也通过了,但是101之所以通过是因为当1100101b向右移动5位时,你得到11b。因此,前三个值分别为37、70和101。 - Jon Skeet
@harold 32 不会通过:32 >> 32 == 32 - assylias
@harold:显然是这样。32不会被移位(因为32%32 == 0),所以结果最终为false。 - Jon Skeet
啊,我看到我在代码里犯了一个傻瓜式的拼写错误...对此感到抱歉。 - harold

1
也许这个谜题的重点是看你是否考虑到了超出0到31位的移位,以及会发生什么。
对于负数来说,情况变得更加奇怪。
for(int n=-70;n<=200;n++)
    if (((n >> n) & 1L) > 0)
        System.out.print(n + " ");

打印

-70 -69 -68 -67 -66 -65 -58 -57 -56 -55 -54 -53 -52 -51 -50 -49 -48 -47 -46 -45 -44 -43 -42 -41 -40 -39 -38 -37 -36 -35 -34 -33 -27 -26 -25 -24 -23 -22 -21 -20 -19 -18 -17 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 37 70 101 102 135 165 167 198 199

n是一个int时,类似的公式

n & (1 << (n & 31)) != 0

如果 n 是一个 long

n & (1L << (n & 63)) != 0

在移位后,更多的负数会有一个1,因为它们被符号扩展了。

一个类似的谜题。

http://vanillajava.blogspot.co.uk/2012/01/another-shifty-challenge.html

http://vanillajava.blogspot.co.uk/2012/01/shifting-challenge.html


1
对于正数而言,该函数似乎仅在数字的形式为以下形式时返回true:
sum_k (alpha_k * 2^k + d(k)), where 

alpha_k = 0 or 1
k >= 5
d(k) = k for exactly one of the k where alpha_k = 1 and 0 otherwise

例子:

alpha_k = 1 for k = 5, 0 otherwise => 32 + 5 = 37
alpha_k = 1 for k = 6, 0 otherwise => 64 + 6 = 70
alpha_k = 1 for k = 5 and 6, 0 otherwise => 32 + 5 + 64 = 101
                                         or 32 + 64 + 6 = 102

所有这些数字都可以使用:

将该数字本身移位%32,将其移位d(k)以获得非空的k。
进入位置1的位于位置k,根据定义alpha_k = 1,因此k为1。

证明只有这些数字有效有点具有挑战性...

下一个问题显然是:这有什么意义?!


0

>> 是有符号右移运算符,左操作数是要进行移位的整数,右操作数是要将整数移位的位数。最终的 & 1L 操作测试第零位:如果第零位为 1,则函数返回 true。我不知道这个的真正目的是什么,但是这个函数返回 true 的结果集取决于操作数的大小,例如对于 32 位 int,片段 (n >> n) 对于 32 的倍数返回非零结果,然后...

32:   (n>>n): 32   (n>>n)&1L: 0
33:   (n>>n): 16   (n>>n)&1L: 0
34:   (n>>n): 8   (n>>n)&1L: 0
35:   (n>>n): 4   (n>>n)&1L: 0
36:   (n>>n): 2   (n>>n)&1L: 0
37:   (n>>n): 1   (n>>n)&1L: 1

or

192:   (n>>n): 192   (n>>n)&1L: 0
193:   (n>>n): 96   (n>>n)&1L: 0
194:   (n>>n): 48   (n>>n)&1L: 0
195:   (n>>n): 24   (n>>n)&1L: 0
196:   (n>>n): 12   (n>>n)&1L: 0
197:   (n>>n): 6   (n>>n)&1L: 0
198:   (n>>n): 3   (n>>n)&1L: 1
199:   (n>>n): 1   (n>>n)&1L: 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接