@eng.Fouad, talk about taking a quick solution and trashing it with no fewer than 2 function calls.
–
Stargazer712Jul 8 '11 at 21:55

14

If you really want to get rid of the majick 31, the right way is return (i|-i) >>> (Integer.SIZE-1);. I certainly wouldn't do it out of forward-compatibility concerns, though - only to make it clear where the 31 came from. There is far, far too much code that would break for them to ever change the size of an int.
–
Ed StaubJul 9 '11 at 0:53

1

@Eng.Fouad - Who would have thought a dozen characters would be worth 300+ rep?
–
Ed StaubJul 9 '11 at 15:03

3

@Ed Staub: It's not the dozen characters. It's knowing what to do with them.
–
T.J. CrowderJul 12 '11 at 14:10

If the objection to a conditional was based on performance concerns, surely this cure is worse than the disease.
–
Ed StaubJul 8 '11 at 18:20

1

@Ed, I for one did not see any mention of performance in the original question. Indeed, the divide and catch example gave me the impression of some entirely different motivation.
–
Dilum RanatungaJul 8 '11 at 18:22

4

This is kinda cheating since Math.abs has a conditional internally : p
–
sshanninJul 8 '11 at 18:24

He was asking for fast, not succint.
–
Martin KonicekJul 8 '11 at 22:56

If you read my question, you'll see I wasn't asking for fast, nor succinct. I was just asking for a bit-twiddly way of eliminating the conditional, since I find this sort of thing fun.
–
CromTheDestroyerJul 9 '11 at 1:48

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.

If he wanted a boolean, he could have written return x == 0.
–
phlogratosJul 8 '11 at 18:24

3

Yeah. I had some sort of idea bouncing around in my head about bit patterns, but by the time it came out it was nonsense. I'm going to leave this answer undeleted in case anyone needs a laugh.
–
Tom AndersonJul 8 '11 at 18:26

@Eng.Fouad: Nice! I could feel this would be done with | and ~, but I couldn't quite think of it myself. Although, if you replace (~i + 1) with -i, it would be a bit better.
–
CromTheDestroyerJul 8 '11 at 18:36

@Eng.Fouad: Your revised version doesn't work. compute(1) would return -1, for example. The best answer is probably (1|-1)>>>31, pointed out by Ed.
–
CromTheDestroyerJul 8 '11 at 18:59

4

@Orion Adrian: When would that happen? With Java's backwards compatibility, I doubt they'd change the bit length of an int. They'd probably just add a new type superlong for 128 bit numbers.
–
Bart van HeukelomJul 8 '11 at 22:16

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.

Totally correct, except where very extreme performance requirements pertain, as in image processing. In that case, using the solution I suggested in a "final" method should eliminate any branching that might cause a pipeline stall. But I think this was meant mostly as a puzzle.
–
Ed StaubJul 8 '11 at 20:37

1

@Ed, on the right hardware with the right hotspot, the conditional can evaluate faster than the two operation bit math. Also, on hardware that does pay for the conditional, the ? 0 : 1 expression is a relatively easy expression to optimize at the compiler/hotspot level, right?
–
Dilum RanatungaJul 8 '11 at 22:10

@Dilum, of course there's theoretically hardware where your mileage may differ. And if hotspot recognized the entire expression, it might JIT-compile it down to a single instruction on some theoretical machine that had such an instruction. But on most machines, the expression (i|-i) >>> 31 should JIT-compile it down, with no optimization at all, down to 3 instructions (negate, or, shift), with no memory accesses beyond the initial load and final store, with no branches, on nearly all machines. That's pretty hard to beat. cont...
–
Ed StaubJul 8 '11 at 23:12

The best I'd expect with branching, on most machines, would be 4 - negate, or, branch-if-0 (with potential stall), and load. Add another fraction if the compiler isn't willing to use two return statements.
–
Ed StaubJul 8 '11 at 23:14

@ncmathsadist: Eh - does no one read tags? I clearly marked this "code-kata" just to avoid this sort of answer. @Ed Staub is right - it's just a puzzle. Also, why are you mentioning my implementation with the exception? I clearly stated that was an example of what I didn't want.
–
CromTheDestroyerJul 9 '11 at 1:52