Vous ne pouvez pas demander la séquence le plus rapide sans donner contraintes sur la machine sur laquelle cela doit fonctionner. Par exemple, certaines machines supportent une instruction appelée "count leading zeroes" ou ont des moyens de l'émuler très rapidement. Si vous pouvez accéder à cette instruction (par exemple avec gcc), vous pouvez écrire:
#include <limits.h>
#include <stdint.h>
uint32_t f(uint32_t x)
{
return ((uint64_t)1)<<(32-__builtin_clz(x)-1);
}
int main()
{
printf("=>%d\n",f(5));
printf("=>%d\n",f(9));
}
f (x) retourne ce que vous voulez (le moins y avec x> = y et y = 2 ** n). Le compilateur va maintenant générer la séquence de code optimale pour la machine cible. Par exemple, lors de la compilation pour une architecture x86_64 par défaut, f() ressemble à ceci:
bsrl %edi, %edi
movl $31, %ecx
movl $1, %eax
xorl $31, %edi
subl %edi, %ecx
salq %cl, %rax
ret
Vous voyez, pas de boucles ici! 7 instructions, pas de branches.
Mais si je dis à mon compilateur (gcc-4.5) pour optimiser la machine que je utilise en ce moment (AMD Phenom II), alors ce sort pour f():
bsrl %edi, %ecx
movl $1, %eax
salq %cl, %rax
ret
Cette est probablement le moyen le plus rapide d'aller chercher cette machine.
EDIT: f (0) aurait abouti à UB, j'ai résolu cela (et l'ensemble). En outre, uint32_t signifie que je peux écrire 32 sans se sentir coupable :-)
J'ai changé vos représentations binaires pour qu'elles correspondent aux décimales (les deux étaient fausses), et j'ai changé l'une des décimales; j'espère que c'est maintenant ce que vous vouliez dire, je n'étais pas positif –
Voir les questions précédentes qui sont pratiquement identiques: http://stackoverflow.com/questions/2679815/previous-power-of-2 et http://stackoverflow.com/questions/2893525/get-the-leftmost-bit –
Wow, c'est un nettoyage impressionnant. En supposant que vous avez bien compris, vous avez réussi à transformer cette question d'incompréhensible en bien posée. Bien sûr, c'est toujours dupe. – nmichaels