f(int x){return x == 0? 0:1;在没有条件的Java中

时间:2011-07-08 18:04:13

标签: java bit-manipulation

我想在Java中实现f(int x) { return x == 0 ? 0 : 1; }

在C中,我只是" return !!x;",但!在Java中的工作方式不同。有没有办法在没有条件的情况下做到这一点?没有像展开版

那样俗气的东西
int ret = 0;
for (int i = 0; i < 32; i++) {
    ret |= ((x & (1 << i)) >>> i);
}

try {
   return x/x;
} catch (ArithmeticException e) {
   return 0;
}

修改

所以,我做了三个不同解决方案的微基准测试:

  1. 我的返回x / x catch解决方案,
  2. 明显的x == 0?0:1解决方案,
  3. Ed Staub的解决方案:(x | -x)&gt;&gt;&gt; 31。
  4. 随机int输入的时间(整个int范围)是:

    1. 0.268716  
    2. 0.324449  
    3. 0.347852  
    

    是的,我的傻瓜x / x解决方案的速度非常快。当你认为其中只有很少的0时,并不是很令人惊讶,并且在绝大多数情况下会采取快速路径。

    50%输入为0的更有趣案例的时间安排:

    1. 1.256533  
    2. 0.321485  
    3. 0.348999  
    

    天真的x==0?0:1解决方案比聪明的解决方案(在我的机器上)快5%左右。我明天会尝试做一些拆解,找出原因。

    EDIT2: 好的,所以条件版本的反汇编是(不包括簿记):

    testl rsi,rsi
    setnz rax
    movzbl rax,rax
    

    (x | -x)&gt;&gt;&gt; 31的反汇编是:

    movl rax,rsi
    negl rax
    orl rax,rsi
    sarl rax,#31
    

    我认为不需要说任何其他事情。

8 个答案:

答案 0 :(得分:42)

好的,没有条件的最短解决方案可能是:

return (i|-i) >>> 31;

答案 1 :(得分:11)

这是一个解决方案:

public static int compute(int i)
{
    return ((i | (~i + 1)) >> 31) & 1; // return ((i | -i) >> 31) & 1
}

修改

或者你可以让它变得更简单:

public static int compute(int i)
{
    return -(-i >> 31); // return -i >>> 31
}

<强> EDIT2:

最后一个解决方案因负数而失败。看看@Ed Staub的解决方案。

<强> EDIT3:

@Orion Adrian好,这是一般解决方案:

public static int compute(int i)
{
    return (i|-i) >>> java.math.BigInteger.valueOf(Integer.MAX_VALUE).bitLength();
}

答案 2 :(得分:8)

int f(int x) {
    return Math.abs(Integer.signum(x));
}

signum()函数返回数字的符号为-1,0或1.所以剩下的就是将-1变为1,这就是abs的作用。

答案 3 :(得分:7)

signum函数以这种方式实现它

return (i >> 31) | (-i >>> 31);

所以,只需添加另一个按位操作即可返回01

return ((i >> 31) | (-i >>> 31)) & 1;

答案 4 :(得分:7)

所有这些解决方案似乎都受到了不同程度努力去理解的弊端。这意味着必须稍后阅读和维护此代码的程序员将不得不花费不必要的努力。这需要钱。

表达式

(x == 0)? 0:1

简单易懂。这是真正做到这一点的正确方法。在普通的代码运行中使用异常是非常可怕的。例外情况是处理程序员控制之外的情况,而不是普通的日常操作。

答案 5 :(得分:1)

我想知道编译器会把它变成什么......

class kata {

    public static int f(int x){
     return -(Boolean.valueOf(x==0).compareTo(true));
    }

     public static void main(String[] args) {
         System.out.println(f(0));
         System.out.println(f(5));
         System.out.println(f(-1));

     }
}

http://ideone.com/ssAVo

答案 6 :(得分:0)

这个问题简化为:“有没有办法将boolean true,false分别映射到int 1,0而不编写条件。”

在Java中,true没有1的标准化处理。最接近的是使用-1。正如@Ed所说,三元运算符就像你得到的那样简洁。

答案 7 :(得分:0)

如果你想要一个布尔值,我想:

return x == x >>> 1

会这样做,因为移位时设置位不移动的唯一数字是没有设置位的数字。

在幕后,字节码实际上使用1和0表示true和false,但我不知道如何在没有某种条件的情况下将Java语言布尔值转换为相应的int值。