Cro*_*yer 31 java bit-manipulation
我想f(int x) { return x == 0 ? 0 : 1; }用Java 实现.
在C中,我只是" return !!x;",但!在Java中并不像那样.有没有办法在没有条件的情况下做到这一点?没有像展开版本那样俗气的东西
int ret = 0;
for (int i = 0; i < 32; i++) {
ret |= ((x & (1 << i)) >>> i);
}
Run Code Online (Sandbox Code Playgroud)
要么
try {
return x/x;
} catch (ArithmeticException e) {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
)
编辑:
所以,我做了三个不同解决方案的微基准测试:
随机int输入的时间(整个int范围)是:
1. 0.268716
2. 0.324449
3. 0.347852
Run Code Online (Sandbox Code Playgroud)
是的,我的愚蠢的x/x解决方案的速度非常快.当您考虑到其中只有很少的0时,并不是很令人惊讶,并且在绝大多数情况下都会采用快速路径.
50%输入为0的更有趣案例的时间安排:
1. 1.256533
2. 0.321485
3. 0.348999
Run Code Online (Sandbox Code Playgroud)
天真的x==0?0:1解决方案比聪明的解决方案快了约5%(在我的机器上).我明天会尝试做一些拆卸,找出原因.
EDIT2: 好的,所以条件版本的反汇编是(不包括簿记):
testl rsi,rsi
setnz rax
movzbl rax,rax
Run Code Online (Sandbox Code Playgroud)
(x | -x)>>> 31的反汇编是:
movl rax,rsi
negl rax
orl rax,rsi
sarl rax,#31
Run Code Online (Sandbox Code Playgroud)
我认为还有什么需要说的.
Ed *_*aub 42
好吧,没有条件的最短解决方案可能是:
return (i|-i) >>> 31;
Run Code Online (Sandbox Code Playgroud)
Eng*_*uad 11
这是一个解决方案:
public static int compute(int i)
{
return ((i | (~i + 1)) >> 31) & 1; // return ((i | -i) >> 31) & 1
}
Run Code Online (Sandbox Code Playgroud)
编辑:
或者你可以使它更简单:
public static int compute(int i)
{
return -(-i >> 31); // return -i >>> 31
}
Run Code Online (Sandbox Code Playgroud)
EDIT2:
最后的解决方案失败,负数.看看@Ed Staub的解决方案.
EDIT3:
@Orion Adrian OK,这是一个通用解决方案:
public static int compute(int i)
{
return (i|-i) >>> java.math.BigInteger.valueOf(Integer.MAX_VALUE).bitLength();
}
Run Code Online (Sandbox Code Playgroud)
int f(int x) {
return Math.abs(Integer.signum(x));
}
Run Code Online (Sandbox Code Playgroud)
该signum()函数返回数字的符号为-1,0或1.所以剩下的就是将-1变为1,这就是做什么abs.
该signum函数以这种方式实现它
return (i >> 31) | (-i >>> 31);
Run Code Online (Sandbox Code Playgroud)
所以,只需添加另一个按位操作返回0或1
return ((i >> 31) | (-i >>> 31)) & 1;
Run Code Online (Sandbox Code Playgroud)
所有这些解决方案似乎都受到了不同程度努力去理解的弊端.这意味着必须稍后阅读和维护此代码的程序员将不得不花费不必要的努力.这要花钱.
表达方式
(x == 0)? 0:1
Run Code Online (Sandbox Code Playgroud)
很简单易懂.这是真正做到这一点的正确方法.在普通的代码运行中使用异常是非常可怕的.例外情况是处理程序员控制之外的情况,而不是普通的日常操作.