Как вычислить целочисленное абсолютное значение без использования условия if. Думаю, нам нужно использовать некоторую побитную операцию. Может ли кто-нибудь помочь?
Как вычислить целочисленную абсолютную величину
Ответ 1
1) Установите маску как правое смещение целого числа на 31 (предполагая, что целые числа сохраняются как 32-битные значения с двумя дополнениями и что оператор с правом сдвигом выполняет подписку на расширение).
mask = n>>31
2) XOR маску с номером
mask ^ n
3) Вычитайте маску из результата шага 2 и верните результат.
(mask^n) - mask
Ответ 2
То же, что и существующие ответы, но с дополнительными пояснениями:
Предположим, что номер двоичного дополнения (как обычный случай, и вы не говорите иначе) и предположим, что 32-бит:
Сначала мы выполняем арифметический сдвиг вправо на 31 бит. Это смещение во всех 1
для отрицательного числа или всего 0
для положительного (но обратите внимание, что фактическое поведение >>
-оператора в C или С++ является реализацией, определенной для отрицательных чисел, но обычно также выполняет арифметику shift, но позвольте просто предполагать псевдокод или фактические аппаратные инструкции, так как это звучит как домашнее задание в любом случае):
mask = x >> 31;
Итак, мы получаем 111...111
(-1) для отрицательных чисел и 000...000
(0) для положительных
Теперь мы XOR это с x
, получим поведение NOT для mask=111...111
(отрицательный) и no-op для mask=000...000
(положительный):
x = x XOR mask;
И, наконец, вычитаем нашу маску, что означает +1 для негативов и + 0/no-op для положительных значений:
x = x - mask;
Итак, для положительных элементов мы выполняем XOR с 0 и вычитанием 0 и, таким образом, получаем одинаковое число. А для негативов мы получили (NOT x) + 1
, что в точности -x
при использовании двухкомпонентного представления.
Ответ 3
Предположим, что int
имеет 32-разрядную версию.
int my_abs(int x)
{
int y = (x >> 31);
return (x ^ y) - y;
}
Ответ 4
Можно также выполнить описанную выше операцию как:
return n*(((n>0)<<1)-1);
где n
- это число, абсолютное значение которого необходимо вычислить.
Ответ 5
Я написал свой собственный, прежде чем открывать этот вопрос.
Мой ответ, вероятно, медленнее, но все еще действителен:
int abs_of_x = ((x*(x >> 31)) | ((~x + 1) * ((~x + 1) >> 31)));
Ответ 6
В C вы можете использовать объединения для выполнения бит-манипуляций в двухлокальных. Следующее будет работать в C и может использоваться как для целых чисел, так и для чисел с плавающей точкой и удвоения.
/**
* Calculates the absolute value of a double.
* @param x An 8-byte floating-point double
* @return A positive double
* @note Uses bit manipulation and does not care about NaNs
*/
double abs(double x)
{
union{
uint64_t bits;
double dub;
} b;
b.dub = x;
//Sets the sign bit to 0
b.bits &= 0x7FFFFFFFFFFFFFFF;
return b.dub;
}
Обратите внимание, что это предполагает, что удваивается 8 байтов.
Ответ 7
Какой язык программирования вы используете? В С# вы можете использовать метод Math.Abs:
int value1 = -1000;
int value2 = 20;
int abs1 = Math.Abs(value1);
int abs2 = Math.Abs(value2);
Ответ 8
Для сборки наиболее эффективным было бы инициализировать значение до 0, вычесть целое число и затем взять max:
pxor mm1, mm1 ; set mm1 to all zeros
psubw mm1, mm0 ; make each mm1 word contain the negative of each mm0 word
pmaxswmm1, mm0 ; mm1 will contain only the positive (larger) values - the absolute value