Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I want to implement f(int x) { return x == 0 ? 0 : 1; } in 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

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.

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

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.

The timings for the more interesting case where 50% of inputs are 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.

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

testl rsi,rsi setnz rax movzbl rax,rax 

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

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

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

like image 706
CromTheDestroyer Avatar asked Jul 08 '11 18:07

CromTheDestroyer


1 Answers

Ok, shortest solution without conditional is probably:

return (i|-i) >>> 31; 
like image 64
Ed Staub Avatar answered Oct 01 '22 01:10

Ed Staub