Хорошо, я, наконец, понял, как сделать это эффективно:
Java:
int f(int x, int y) {
return (((x >> 31) | ((unsigned)-x >> 31))^y) - y;
}
C/C++:
int f(int x, int y) {
return (((x > 0) - (x < 0))^y) - y;
}
Приведенные выше функции возвращают -sgn(x)
у есть -1 и sgn(x)
othe rwise.
Или, если нам просто нужно работать для каждого значения, отличного от -2^31 (минимальное значение без знака int), с сохранением абсолютного значения, это функция, которая переворачивает знак, в зависимости от переменной у:
int f(int x, int y) {
return (x^y) - y; // returns -x for y == -1, x otherwise
}
вывод: -x == ~ х + 1 == (х^0xFFFFFFFF) + 1 == (х^-1) + 1 == (х^-1) - (-1). Подставляя -1 с y, мы получаем формулу с двумя переменными, которая имеет интересное свойство, которое возвращает неизмененное x, если y задано равным 0, потому что ни (x^0), ни вычитание 0 не изменяет результат. Теперь угол случае, если x равна 0x8000000, когда эта формула не работает. Это можно исправить, применяя функцию sgn (x), поэтому мы имеем (sgn(x)^y) - y)
. Наконец, мы заменим функции sgn (x) на хорошо известные формулы, не использующие ветвление.
Целое или с плавающей точкой? –
Мне нужны флип целочисленные значения, возможно, без переполнения. – eold
Вы хотите предпринять разные действия, основанные на неизвестной постоянной константе, без ветвления? –