Как я могу проверить, является ли целое число со знаком положительным? - PullRequest
6 голосов
/ 17 сентября 2010

Используя побитовые операторы, и я предполагаю сложение и вычитание, как я могу проверить, является ли целое число со знаком положительным (в частности, не отрицательным и не нулевым)? Я уверен, что ответ на этот вопрос очень прост, но он просто не приходит ко мне.

Ответы [ 5 ]

5 голосов
/ 17 сентября 2010

Если вы действительно хотите предикат "строго положительный" для int n без использования условных выражений (при условии дополнения до 2):

  • -n будет иметь бит знака (верхний), если n был строго положительным, и сбрасывается во всех других случаях , за исключением n == INT_MIN;
  • ~n будет иметь установленный бит знака, если n был строго положительным, или 0, и очищаться во всех других случаях , включая n == INT_MIN;
  • ... поэтому -n & ~n будет иметь установленный бит знака, если n было строго положительным, и очищаться во всех других случаях.

Примените беззнаковое смещение, чтобы превратить это в ответ 0/1:

int strictly_positive = (unsigned)(-n & ~n) >> ((sizeof(int) * CHAR_BIT) - 1);

РЕДАКТИРОВАТЬ: как указано в комментариях caf, -n вызывает переполнение, когда n == INT_MIN (все еще предполагается, что дополнение 2). Стандарт C позволяет программе в этом случае не работать (например, вы можете включить прерывания для переполнения со знаком, используя GCC с опцией -ftrapv). Приведение n к беззнаковому исправляет проблему (арифметика без знака не вызывает переполнения). Таким образом, улучшение будет:

unsigned u = (unsigned)n;
int strictly_positive = (-u & ~u) >> ((sizeof(int) * CHAR_BIT) - 1);
3 голосов
/ 17 сентября 2010

Если вы не можете использовать очевидные операторы сравнения, вам придется работать усерднее:

int i = anyValue;
if (i && !(i & (1U << (sizeof(int) * CHAR_BIT - 1))))
    /* I'm almost positive it is positive */

Первый член проверяет, что значение не равно нулю;вторая проверяет, что значение не имеет установленного начального бита.Это должно работать для целых чисел 2-дополнения, дополнения 1 или величины знака.

3 голосов
/ 17 сентября 2010

Отметьте самый значимый бит. 0 положительно, 1 отрицательно.

1 голос
/ 17 сентября 2010

Рассмотрим, как представляется подпись.Часто это делается с помощью дополнения до двух или с помощью простого знака - я думаю, что оба из них можно проверить с помощью простого логического и.

0 голосов
/ 17 сентября 2010

Убедитесь, что это не 0 и самый старший бит 0, что-то вроде:

int positive(int x) {
   return x && (x & 0x80000000);
}
...