20

I'm wondering if there's a way to convert a boolean to an int without using if statements (as not to break the pipeline). For example, I could write

int boolToInt( boolean b ){
  if ( b )
    return 1
  return 0

But I'm wondering if there's a way to do it without the if statement, like Python's

bool = True 
num = 1 * ( bool )

I also figure you could do

boolean bool = True;
int myint = Boolean.valueOf( bool ).compareTo( false );

This creates an extra object, though, so it's really wasteful and I found it to be even slower than the if-statement way (which isn't necessarily inefficient, just has the one weakness).

en_Knight
  • 5,301
  • 2
  • 26
  • 46
  • what do you mean by "as not to break the pipeline"? – assylias Jun 01 '13 at 01:35
  • And your second piece of code does the exact same thing (i.e. it uses an if). – assylias Jun 01 '13 at 01:36
  • 1
    http://stackoverflow.com/questions/315306/is-if-expensive I think addresses the pipeline issue well – en_Knight Jun 01 '13 at 01:39
  • 2
    The question is moot. At the absolute lowest level, whatever the language, the truth remains that some branching will occur. And this kind of branching is so fast that it can happen 10^n times, n <= 10, without your having the time to blink. So, ultimately: why does it matter at all? – fge Jun 01 '13 at 01:47
  • @assylias see my answer - although trite, it may qualify :) – Bohemian Jun 01 '13 at 01:51
  • 1
    I won't put this as an answer as it's not faster, but here's another way to do it: `return (Boolean.valueOf(b).hashCode() >> 1) & 1;` The return value of Boolean.valueOf is always one of the class constants so there's no object creation overhead, but it still involves two (hidden) `if`s. – Boann Jun 01 '13 at 02:07
  • Why exactly are you using boolean instead of int? Just curious, because I think boolean uses as much memory space as integer. – Horse SMith Sep 23 '15 at 09:16
  • @fge Why would branching have to occur? Can't/doesn't the JVM store true as 1 and false as zero? – Marko Topolnik Dec 24 '16 at 15:00

12 Answers12

31

You can't use a boolean other than in a if. However it does not mean that there will be a branch at the assembly level.

If you check the compiled code of that method (by the way, using return b ? 1 : 0; compiles to the exact same instructions), you will see that it does not use a jump:

0x0000000002672580: sub    $0x18,%rsp
0x0000000002672587: mov    %rbp,0x10(%rsp)    ;*synchronization entry
0x000000000267258c: mov    %edx,%eax
0x000000000267258e: add    $0x10,%rsp
0x0000000002672592: pop    %rbp
0x0000000002672593: test   %eax,-0x2542599(%rip)        # 0x0000000000130000
                                                ;   {poll_return}
0x00000000025b2599: retq  

Note: this is on hotspot server 7 - you might get different results on a different VM.

assylias
  • 321,522
  • 82
  • 660
  • 783
13

Use the ?: operator: ( b ? 1 : 0 )

Shadow Man
  • 3,234
  • 1
  • 24
  • 35
  • 4
    I believe that the ternary operator is just sugar for an if-statemnent. Is that incorrect? – en_Knight Jun 01 '13 at 01:36
  • 1
    @mjCSguy it is essentially an inline if statement <-- over simplification – Shadow Man Jun 01 '13 at 01:38
  • 1
    That does not answer the question of how a branch can be avoided. – assylias Jun 01 '13 at 01:41
  • @mjCSguy whether you use `if` or the `?:` operator, it is highly likely that the JVM, due to JIT, will optimize to the same runtime bytecode eventually, so... – fge Jun 01 '13 at 01:42
  • @assylias the question is, at the lowest level, can a branch be avoided? Answer: no. – fge Jun 01 '13 at 01:42
  • @fge Agreed, as commented below the question. – assylias Jun 01 '13 at 01:43
  • @assylias I read the question as meaning how to do it inline. Not how to avoid a branch, but rather how to avoid an if statement (as was directly stated in the question). – Shadow Man Jun 01 '13 at 01:47
  • I meant without branching. So not just without if statements for the sake of simplicity - yours is certainly more concise - but for efficiency. @fge, you're right that it almost always doesn't matter, but if I had a boolean cast being called a LOT of times, I might start to care, which is why I'm asking. fge and assylias you guys seem to agree that it can't which I accept – en_Knight Jun 01 '13 at 01:54
  • @mjCSguy it is _impossible_ to do without branching at the lowest level anyway. And remember that Java's optimization is done _at runtime_ anyway. Write correct code, the JVM will optimize it away for you! – fge Jun 01 '13 at 01:57
5

You can use the ternary operator:

return b ? 1 : 0;

If this is considered an "if", and given this is a "puzzle", you could use a map like this:

return new HashMap<Boolean, Integer>() {{
    put(true, 1);
    put(false, 0);
}}.get(b);

Although theoretically the implementation of HashMap doesn't need to use an if, it actually does. Nevertheless, the "if" is not in your code.

Of course to improve performance, you would:

private static Map<Boolean, Integer> map = new HashMap<Boolean, Integer>() {{
    put(true, 1);
    put(false, 0);
}};

Then in the method:

return map.get(b);
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 8
    I think the HashMap wins the award for the slowest possible way to do this. – Boann Jun 01 '13 at 01:57
  • 1
    Ya, I appreciate that you DID probably answer the question, but I would be creating objects for primitives, to start. I actually tried that, just to see, but it's predictably really slow. – en_Knight Jun 01 '13 at 02:01
  • 1
    +1 The map solution did answer the question. Actually it's the only answer without a *logical/imperative* if, it uses the *functional* approach. If the HashMap is static, this solution is 6x slower than ternary operator (1000000 iterations: 6 vs 36ms). So in this case it is slower, but generally speaking, starting at a certain limit (regarding the number of values you have to map), the map/hash solution will be faster than a sequence of if statements. – Beryllium Jun 01 '13 at 07:02
  • @Boann i consider this to be a "puzzle" question, so performance is irrelevant. – Bohemian Jun 01 '13 at 07:32
  • @beryllium Hiding the if statement behind a method call can't possibly be the answer. And in HasMap code, it will be more than one if probably. – Marko Topolnik Dec 24 '16 at 14:56
4

Otherwise, you could use the Apache Commons BooleanUtils.toInteger method which works like a charm...

// Converts a boolean to an int specifying the conversion values.    
static int  toInteger(boolean bool, int trueValue, int falseValue)

// Converts a Boolean to an int specifying the conversion values.
static int  toInteger(Boolean bool, int trueValue, int falseValue, int nullValue)
Romain VDK
  • 1,798
  • 1
  • 11
  • 9
2

I found a solution by framework. Use compare for Boolean.

// b = Your boolean result
// v will be 1 if b equals true, otherwise 0
int v = Boolean.compare(b, false);
1

This is not directly possible, not in Java anyway. You could consider directly using an int or byte instead of a boolean if you really need to avoid the branch.

It's also possible that the VM is smart enough to eliminate the branch (the if or ?:) itself in this case, as the boolean's internal representation is quite likely to be the literal 1 or 0 anyway. Here is an article on how to examine the generated native machine code for the Oracle JDK, and if you need speed, make sure you're using the "server" JVM as it performs more aggressive optimization than the "client" one.

Community
  • 1
  • 1
Boann
  • 48,794
  • 16
  • 117
  • 146
1

I can't say I recommend this. It's both slower than the ternary operator by itself, and it's too clever to be called good programming, but there's this:

-Boolean.FALSE.compareTo(value)

It uses the ternary under the covers (a couple of method calls later), but it's not in your code. To be fair, I would be willing to bet that there's a branch somewhere in the Python execution as well (though I probably only bet a nickel ;) ).

Tim Pote
  • 27,191
  • 6
  • 63
  • 65
0

You can try using ternary operator like this

int value = flag ? 1 : 0;
mike
  • 2,149
  • 20
  • 29
Aman Gupta
  • 5,548
  • 10
  • 52
  • 88
0

Since you want no if / else solution your expression is perfect, though I would slightly change it

int myint = Boolean.valueOf( bool ).compareTo( Boolean.FALSE );

There is no object creation involved, Boolean.valueOf(boolean b) returns either Boolean.TRUE or Boolean.FALSE, see API

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • That definitely uses the ternary a few frames later. OP seems to be concerned with performance, so you might want to mention that. Also, you can do that with one less method call. Not that it matters, because you shouldn't be doing this in your code at all ;) – Tim Pote Jun 01 '13 at 02:10
0

A reasonable alternative to ising to the ternary to avoid an "if":

private static Boolean[] array = {false, true};

int boolToInt( boolean b ){
    return Arrays.binarySearch(array, b);
}

Note that I consider this s "puzzle" question, so if coding it myself i would use the ternary..

Bohemian
  • 412,405
  • 93
  • 575
  • 722
0

Nowadays, jdk has delivered a useful Utils method: BooleanUtils.toInteger()

In the source code, the method that jdk realize it must be efficient:

public static int toInteger(boolean bool) {
    return bool ? 1 : 0;
}

So, I think the most votes answer is very great, return bool ? 1 : 0 is the best practice.

Example Code to use BooleanUtils as followed:

BooleanUtils.toInteger(false);
dyy.alex
  • 514
  • 2
  • 4
  • 16
-1
int ansInt = givenBoolean ? 1 : 0;
FelixSFD
  • 6,052
  • 10
  • 43
  • 117
  • @Hermant, three other people already answered this question with the same answer you gave. PLS read for unique answers before adding the same answer again. :-) – mike May 28 '18 at 18:38