Как определить, может ли 32-битное int соответствовать 16-битному короткому - PullRequest
7 голосов
/ 07 сентября 2011

Использование только:

! ~ & ^ | + << >>

Мне нужно выяснить, можно ли представить 32-разрядное целое число со знаком в виде 16-разрядного целого числа с дополнением до двух.

Мои первые мысли были отделить16 битов MSB и 16 битов LSB, а затем использовать маску для последних 16 битов, поэтому, если он не равен нулю, он не сможет быть представлен, а затем использовать это число для проверки битов MSB.

Пример функции, которую мне нужно написать: fitsInShort (33000) = 0 (невозможно представить) и fitsInShort (-32768) = 1 (можно представить)

Ответы [ 5 ]

8 голосов
/ 07 сентября 2011
bool fits16(int x)
{
    short y = x;
    return y == x;
}

Шучу :) Вот реальный ответ, предполагая, что int - это 32 бита, а short - 16 бит и два дополнительных представления:

Редактировать: Пожалуйста, смотрите последнее изменение для правильного ответа!

bool fits16(int x)
{
    /* Mask out the least significant word */
    int y = x & 0xffff0000;
    if (x & 0x00008000) {
        return y == 0xffff0000;
    } else {
        return y == 0;
    }
}

Без утверждений if я полагаю, что должен это сделать:

return (
    !(!(x & 0xffff0000) || !(x & 0x00008000)) ||
    !((x & 0xffff0000) || (x & 0x00008000))
);

Редактировать: Оли прав. Я почему-то думал, что им позволили. Вот последняя попытка с объяснением:

Нам нужно, чтобы 17 старших разрядов x были либо всеми единицами, либо всеми нулями. Итак, начнем с маскировки других битов:

int a = x & 0xffff8000; // we need a to be either 0xffff8000 or 0x00000000
int b = a + 0x00008000; // if a == 0xffff8000 then b is now 0x00000000
                        // if a == 0x00000000 then b is now 0x00008000
                        // in any other case b has a different value
int c = b & 0xffff7fff; // all zeroes if it fits, something else if it doesn't
return c;

Или более кратко:

return ((x & 0xffff8000) + 0x8000) & 0xffff7fff;
8 голосов
/ 07 сентября 2011

Если 32-разрядное число находится в диапазоне [-32768, + 32767], то все 17 мсек будут одинаковыми.

Вот дурацкий способ сказать, является ли 3-битное число всеми единицами или всеми нулями, используя только ваши операции (я предполагаю, что вам не разрешены условные структуры управления, потому что они требуют неявных логических операций):

int allOnes3(int x)
{
    return ((x >> 0) & (x >> 1) & (x >> 2)) & 1;
}

int allTheSame3(int x)
{
    return allOnes3(x) | allOnes3(~x);
}

Я оставлю вас расширять / улучшать эту концепцию.

3 голосов
/ 07 сентября 2011

Вот решение без приведения операторов if и использования только тех операторов, которые вы просили:

#define fitsInShort(x) !(((((x) & 0xffff8000) >> 15) + 1) & 0x1fffe)
0 голосов
/ 07 сентября 2011
short fitsInShort(int x)
{
    int positiveShortRange = (int) ((short) 0xffff / (short) 2);
    int negativeShortRange = (int) ((short) 0xffff / (short) 2) + 1;

    if(x > negativeShortRange && x < positiveShortRange)
        return (short) x;
    else
        return (short) 0;
}
0 голосов
/ 07 сентября 2011
if (!(integer_32 & 0x8000000))
{
   /* if +ve number */
  if (integer_32 & 0xffff8000)
    /* cannot fit */
  else 
    /* can fit */
}
else if (integer_32 & 0x80000000)
{
  /* if -ve number */
  if ( ~((integer_32 & 0xffff8000) | 0x00007fff))
    /* cannot fit */
  else
    /* can fit */
}

First if Сначала проверяет номер + ve, проверяя бит со знаком.Если + ve, то он проверяет, равны ли 0 бита 31 биту 0, если 0, то он не может вписаться в short, иначе он может.все установлено (представление метода дополнения 2).

Следовательно, второе if это число -ve, затем биты с 15 по 31 маскируются, а остальные младшие биты (от 0 до 14) устанавливаются.Если это 0xffffffff, то 0 будет только его дополнение, что означает, что все биты с 15 по 31 установлены, поэтому он может соответствовать (остальная часть), в противном случае он не может соответствовать (условие if).

...