web-dev-qa-db-fra.com

Conversion de booléens en nombres entiers en Java sans if-statement

Je me demande s'il existe un moyen de convertir un booléen en int sans utiliser d'instructions if (pour ne pas interrompre le pipeline). Par exemple, je pourrais écrire

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

Mais je me demande s’il existe un moyen de le faire sans l’instruction if, comme celle de Python 

bool = True 
num = 1 * ( bool )

Je pense aussi que tu pourrais faire 

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

Cela crée cependant un objet supplémentaire, donc c'est vraiment une perte de temps et je l'ai trouvé encore plus lent que la méthode if-statement (qui n'est pas nécessairement inefficace, a juste une faiblesse). 

19
en_Knight

Vous ne pouvez utiliser un booléen que dans un if. Cependant, cela ne signifie pas qu’il y aura une branche au niveau de l’Assemblée.

Si vous vérifiez le code compilé de cette méthode (d'ailleurs, en utilisant return b ? 1 : 0; compile exactement les mêmes instructions), vous verrez qu'il n'utilise pas de saut:

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  

Remarque: il s’agit du serveur Hotspot 7. Vous obtiendrez peut-être des résultats différents sur un ordinateur virtuel différent.

25
assylias

Utilisez l'opérateur?: ( b ? 1 : 0 )

12
Shadow Man

Vous pouvez utiliser l'opérateur ternary :

return b ? 1 : 0;

Si ceci est considéré comme un "si", et étant donné qu'il s'agit d'un "puzzle", vous pouvez utiliser une carte comme celle-ci:

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

Bien que théoriquement, la mise en œuvre de HashMap n'ait pas besoin d'utiliser un if, c'est le cas. Néanmoins, le "si" n'est pas dans le code votre.

Bien sûr, pour améliorer les performances, vous devriez:

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

Puis dans la méthode:

return map.get(b);
4
Bohemian

Sinon, vous pouvez utiliser la méthode Apache Commons BooleanUtils.toInteger qui fonctionne comme un charme ...

// 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)
4
Romain VDK

J'ai trouvé une solution par framework. Utilisez compare pour Boolean.

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

Je ne peux pas dire que je recommande ceci. C'est à la fois plus lent que l'opérateur ternaire en lui-même, et c'est trop intelligent pour être qualifié de bonne programmation, mais il y a ceci:

-Boolean.FALSE.compareTo(value)

Il utilise le ternaire sous les couvertures (quelques appels de méthode plus tard), mais ce n'est pas dans votre code. Pour être juste, je serais prêt à parier qu'il y a aussi une branche quelque part dans l'exécution de Python (bien que je parie probablement que de l'argent;)).

1
Tim Pote

Ce n'est pas directement possible, pas en Java de toute façon. Vous pouvez utiliser directement une variable int ou byte au lieu d'une boolean si vous devez réellement éviter la branche.

Il est également possible que VM soit suffisamment intelligent pour éliminer la branche (la if ou ?:) elle-même dans ce cas, car la représentation interne de la boolean sera probablement le littéral 1 ou 0 de toute façon. Voici un article sur la manière d’examiner le code machine généré pour le JDK Oracle et, si vous avez besoin de rapidité, assurez-vous d’utiliser la "machine virtuelle" JVM car elle effectue une optimisation plus agressive que le "client".

1
Boann

Une alternative raisonnable au ternaire pour éviter un "si":

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

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

Notez que je considère cette question "de puzzle", donc si je le codais moi-même, je voudrais utiliser le ternaire.

0
Bohemian

Vous pouvez essayer d'utiliser un opérateur ternaire comme celui-ci

int value = flag ? 1 : 0;
0
agpt
int ansInt = givenBoolean ? 1 : 0;
0
Hemant Dhanuka

Puisque vous ne voulez pas de solution si/sinon votre expression est parfaite, je la changerais légèrement

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

Boolean.valueOf (boolean b) renvoie soit Boolean.TRUE ou Boolean.FALSE, voir API.

0
Evgeniy Dorofeev