Je veux mettre en œuvre f(int x) { return x == 0 ? 0 : 1; }
en Java.
En C, j'aurais juste " return !!x;
", mais !
ne fonctionne pas comme ça en Java. Existe-t-il un moyen de le faire sans conditionnelles ? Sans quelque chose d'aussi ridicule qu'une version non laminée de
int ret = 0;
for (int i = 0; i < 32; i++) {
ret |= ((x & (1 << i)) >>> i);
}
ou
try {
return x/x;
} catch (ArithmeticException e) {
return 0;
}
)
EDITAR:
J'ai donc réalisé un microbenchmark de trois solutions différentes :
- mon retour x/x attrape la solution,
- la solution évidente x==0?0:1, et
- Solution d'Ed Staub : (x|-x) >>> 31.
Les temps pour des entrées int aléatoires (toute la gamme int) étaient :
1. 0.268716
2. 0.324449
3. 0.347852
Oui, ma stupide solution x/x était plus rapide d'une marge assez importante. Ce n'est pas très surprenant si l'on considère qu'il y a très peu de 0 dans cette solution et que, dans la grande majorité des cas, la solution rapide est utilisée.
Les timings pour le cas le plus intéressant où 50% des entrées sont à 0 :
1. 1.256533
2. 0.321485
3. 0.348999
Les naïfs x==0?0:1
était plus rapide d'environ 5% que la solution intelligente (sur ma machine). Je vais essayer de faire un peu de désassemblage demain pour découvrir pourquoi.
EDIT2 : Ok, donc le désassemblage pour la version conditionnelle est (sans comptabilité) :
testl rsi,rsi
setnz rax
movzbl rax,rax
Le désassemblage pour (x|-x)>>>31 est :
movl rax,rsi
negl rax
orl rax,rsi
sarl rax,#31
Je pense qu'il n'y a rien d'autre à dire.