2010-11-25 20 views
15

dans l'esprit de graphics.stanford.edu/~seander/bithacks.html que je dois résoudre le problème suivant:C/C de Bit bidouilles

int x; 
int pow2; // always a positive power of 2 
int sgn; // always either 0 or 1 
// ... 
// ... 
if(sgn == 0) 
    x -= pow2; 
else 
    x += pow2; 

Bien sûr, je dois éviter le conditionnel. Jusqu'à présent, le meilleur que j'ai trouvé est

x -= (1|(~sgn+1))*pow2 

mais cela implique une multiplication que je voudrais également éviter. Merci d'avance.

EDIT: Merci à tous,

x -= (pow2^-sgn) + sgn 

semble faire l'affaire!

+0

vous devez accepter la réponse, alors. – Simone

+0

Lorsque la multiplication n'est pas un problème, nous avons aussi: 'x - = (1-2 * sgn) * pow', en utilisant le mapping' 0 -> 1' et '1 -> -1', ce qui équivaut' x - > (1-2x) '. – rafak

+0

encore une fois, parenthèses! la précédence de '^' est inférieure à '+', donc 'x - = pow2^-sgn + sgn' est' x - = pow2^(- sgn + sgn) 'est' x - = pow2'. – lijie

Répondre

16

Je voudrais essayer

x -= (pow2^(~sgn+1)) + sgn 

ou, comme suggéré par Lijie dans les commentaires

x -= (pow2^-sgn) + sgn 

Si sgn est 0, ~sgn+1 est également 0, donc pow2^(~sgn+1) == pow2. Si sgn est 1, (~sgn+1) est 0xFFFFFFFF, et (pow2^(~sgn+1)) + sgn == -pow2.

+4

vous pouvez changer '~ sgn + 1' '-sgn'. – lijie

+0

@lijie: Oui, c'est vrai. Merci! –

+2

oh oui. uh '^' est de préséance inférieure à '+', donc je suggère des parenthèses. – lijie

2

Du haut de ma tête:

int subMask = sgn - 1; 
x -= pow2 & subMask; 
int addMask = -sgn; 
x += pow2 & addMask; 

Aucune garantie quant à savoir si cela fonctionne ou que ce soit intelligent, c'est juste une idée au hasard qui a sauté dans ma tête.

EDIT: nous allons faire cela un peu moins lisible (aka plus compact):

x += (pow2 & -sgn) - (pow2 & (sgn-1)); 
4
mask = sgn - 1; // generate mask: sgn == 0 => mask = -1, sgn == 1 => mask = 0 

x = x + (mask & (-pow2)) + (~mask & (pow2)); // use mask to select +/- pow2 for addition 
+0

C'est un conditionnel. –

+4

@Sven: non, '&' est un opérateur bit à bit –

+0

Il y avait un conditionnel quand j'ai posté mon commentaire. Et tu le sais. –

1

Je voudrais changer l'interface et remplacer la multiplication par décalage gauche. (Utiliser exposant au lieu de pow2)

1

Vous pouvez faire quelque chose comme (à partir du lien) x + = ((pow2^-sgn) + SGN)