C/С++ Bit Twiddling
в духе graphics.stanford.edu/~seander/bithacks.html Мне нужно решить следующую проблему:
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;
Конечно, мне нужно избегать условного. Пока лучшее, что я придумал, это
x -= (1|(~sgn+1))*pow2
но это связано с умножением, которое я также хотел бы избежать. Спасибо заранее.
EDIT: Спасибо всем,
x -= (pow2^-sgn) + sgn
похоже, делает трюк!
Ответы
Ответ 1
Я бы попробовал
x -= (pow2 ^ (~sgn+1)) + sgn
или, как было предложено lijie в комментариях
x -= (pow2 ^ -sgn) + sgn
Если sgn
- 0
, ~sgn+1
также 0
, поэтому pow2 ^ (~sgn+1) == pow2
. Если sgn
- 1
, (~sgn+1)
- 0xFFFFFFFF
и (pow2 ^ (~sgn+1)) + sgn == -pow2
.
Ответ 2
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
Ответ 3
Сверху моей головы:
int subMask = sgn - 1;
x -= pow2 & subMask;
int addMask = -sgn;
x += pow2 & addMask;
Никаких гарантий относительно того, работает ли это или нет, это просто случайная идея, которая появилась у меня в голове.
EDIT: сделайте это немного менее читаемым (более компактным):
x += (pow2 & -sgn) - (pow2 & (sgn-1));
Ответ 4
Я бы изменил интерфейс и заменил умножение на левый сдвиг. (Используйте экспоненту вместо pow2)
Ответ 5
Вы можете сделать что-то вроде (по ссылке)
x + = ((pow2 ^ -sgn) + sgn)