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
f(int x) { return x == 0 ? 0 : 1; } in Java without conditionals
提问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:
所以,我做了三个不同解决方案的微基准测试:
- my return x/x catch solution,
- the obvious x==0?0:1 solution, and
- Ed Staub's solution: (x|-x) >>> 31.
- 我的返回 x/x 捕获解决方案,
- 明显的 x==0?0:1 解决方案,以及
- 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:1
solution 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 abs
does.
该signum()
函数返回数字的符号为 -1、0 或 1。所以剩下的就是将 -1 变成 1,这就是abs
。
回答by Yanick Rochon
The signum
function implements it this way
该signum
函数实现这种方式
return (i >> 31) | (-i >>> 31);
so, just add another bitwise operation to return 0
or 1
因此,只需添加另一个按位运算即可返回0
或1
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));
}
}
回答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 true
as 1
. The closest is use of -1
. So as @Ed says, the ternary operator is as succinct as you get.
在 Java 中,没有对true
as 的标准化处理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 值。