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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6628495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 16:42:27  来源:igfitidea点击:

f(int x) { return x == 0 ? 0 : 1; } in Java without conditionals

javabit-manipulation

提问by CromTheDestroyer

I want to implement f(int x) { return x == 0 ? 0 : 1; }in Java.

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

In C, I'd just "return !!x;", but !doesn't work like that in Java. Is there some way to do it without conditionals? Without something cheesy like an unrolled version of

在 C 中,我只是“ return !!x;”,但!在 Java 中不会那样工作。有没有办法在没有条件的情况下做到这一点?没有像展开版本那样俗气的东西

int ret = 0;
for (int i = 0; i < 32; i++) {
    ret |= ((x & (1 << i)) >>> i);
}

or

或者

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

)

)

EDIT:

编辑:

So, I did a microbenchmark of three different solutions:

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

  1. my return x/x catch solution,
  2. the obvious x==0?0:1 solution, and
  3. Ed Staub's solution: (x|-x) >>> 31.
  1. 我的返回 x/x 捕获解决方案,
  2. 明显的 x==0?0:1 解决方案,以及
  3. Ed Staub 的解决方案:(x|-x) >>> 31。

The timings for random int inputs (the whole int range) were:

随机 int 输入(整个 int 范围)的时间为:

1. 0.268716  
2. 0.324449  
3. 0.347852  

Yes, my stupid x/x solution was faster by a pretty hefty margin. Not very surprising when you consider that there are very few 0's in it, and in the vast majority of cases the fast path is taken.

是的,我愚蠢的 x/x 解决方案的速度要快得多。当您考虑到其中很少有 0 时,这并不奇怪,并且在绝大多数情况下都采用了快速路径。

The timings for the more interesting case where 50% of inputs are 0:

50% 的输入为 0 的更有趣情况的计时:

1. 1.256533  
2. 0.321485  
3. 0.348999  

The naive x==0?0:1solution was faster by about 5% than the clever one (on my machine). I'll try to do some disassembly tomorrow to find out why.

天真的x==0?0:1解决方案比聪明的解决方案(在我的机器上)快了大约 5%。明天我将尝试进行一些拆卸以找出原因。

EDIT2:Ok, so the disassembly for the conditional version is (excluding book-keeping):

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

testl rsi,rsi
setnz rax
movzbl rax,rax

The disassembly for (x|-x)>>>31 is:

(x|-x)>>>31 的反汇编是:

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

I don't think anything else needs to be said.

我认为不需要再说什么了。

回答by Ed Staub

Ok, shortest solution without conditional is probably:

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

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

回答by Eng.Fouad

Here is a solution:

这是一个解决方案:

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

EDIT:

编辑:

or you can make it more simple:

或者你可以让它更简单:

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

EDIT2:

编辑2:

last solution fails with negative numbers. Take a look at @Ed Staub's solution.

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

EDIT3:

编辑3:

@Orion Adrian OK, here is a general solution:

@Orion Adrian 好的,这是一个通用的解决方案:

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

回答by phlogratos

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

The signum()function returns the sign of the number as -1, 0 or 1. So all what's left is to turn -1 into 1, which is what absdoes.

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

回答by Yanick Rochon

The signumfunction implements it this way

signum函数实现这种方式

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

so, just add another bitwise operation to return 0or 1

因此,只需添加另一个按位运算即可返回01

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

回答by ncmathsadist

All of these solutions seem to suffer from the vice of taking varying degrees of effort to understand. That means the programmer who must later read and maintain this code will have to expend unnecessary effort. That costs money.

所有这些解决方案似乎都因需要付出不同程度的努力来理解而受到影响。这意味着以后必须阅读和维护此代码的程序员将不得不付出不必要的努力。那是要花钱的。

The expression

表达方式

(x == 0)? 0:1

is straightforward and simple to understand. It's really the right way to do this. The use of an exception in the ordinary run of code is downright ghastly. Exceptions are for handling circumstances beyond programmer control, not for ordinary routine operations.

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

回答by jmoreno

I wonder what the compiler would turn this into...

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

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

http://ideone.com/ssAVo

回答by Dilum Ranatunga

This question reduces down to: "Is there a way to map boolean true,false to int 1,0 respectively without writing the conditional."

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

In Java, there is no standardized treatment of trueas 1. The closest is use of -1. So as @Ed says, the ternary operator is as succinct as you get.

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

回答by Tom Anderson

If you wanted a boolean, i think:

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

return x == x >>> 1

Would do it, because the only number whose set bits don't move when shifted is one with no set bits.

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

Under the hood, the bytecode actually uses 1 and 0 for true and false, but i don't know of any way to turn a Java language boolean value into its corresponding int value without some sort of conditional.

在幕后,字节码实际上使用 1 和 0 来表示真假,但我不知道有什么方法可以在没有某种条件的情况下将 Java 语言布尔值转换为其相应的 int 值。