Подтвердить что ты не робот

Как вычислить целочисленную абсолютную величину

Как вычислить целочисленное абсолютное значение без использования условия if. Думаю, нам нужно использовать некоторую побитную операцию. Может ли кто-нибудь помочь?

4b9b3361

Ответ 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