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

Проверка того, является ли число положительным или отрицательным с помощью побитовых операторов

Я могу проверить, является ли число нечетным/четным с помощью побитовых операторов. Могу ли я проверить, является ли число положительным/нулевым/отрицательным, без использования каких-либо условных операторов/операторов, например if/ternary и т.д.

Можно ли это сделать с помощью побитовых операторов и некоторого трюка в C или на С++?

4b9b3361

Ответ 1

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

Конечно:

bool is_positive = number > 0;
bool is_negative = number < 0;
bool is_zero = number == 0;

Ответ 2

Если высокий бит установлен на целое число со знаком (байты, длинные и т.д., но не число с плавающей запятой), это число отрицательно.

int x = -2300;  // assuming a 32-bit int

if ((x & 0x80000000) != 0)
{
    // number is negative
}

ДОБАВЛЕНО:

Вы сказали, что не хотите использовать какие-либо условные обозначения. Я полагаю, вы могли бы это сделать:

int isNegative = (x & 0x80000000);

И через некоторое время вы можете проверить его с помощью if (isNegative).

Ответ 3

Подробное обсуждение страницы бит Twiddling Hacks.

int v;      // we want to find the sign of v
int sign;   // the result goes here 

// CHAR_BIT is the number of bits per byte (normally 8).
sign = -(v < 0);  // if v < 0 then -1, else 0. 
// or, to avoid branching on CPUs with flag registers (IA32):
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// or, for one less instruction (but not portable):
sign = v >> (sizeof(int) * CHAR_BIT - 1); 

// The last expression above evaluates to sign = v >> 31 for 32-bit integers.
// This is one operation faster than the obvious way, sign = -(v < 0). This
// trick works because when signed integers are shifted right, the value of the
// far left bit is copied to the other bits. The far left bit is 1 when the value
// is negative and 0 otherwise; all 1 bits gives -1. Unfortunately, this behavior
// is architecture-specific.

// Alternatively, if you prefer the result be either -1 or +1, then use:

sign = +1 | (v >> (sizeof(int) * CHAR_BIT - 1));  // if v < 0 then -1, else +1

// On the other hand, if you prefer the result be either -1, 0, or +1, then use:

sign = (v != 0) | -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1));
// Or, for more speed but less portability:
sign = (v != 0) | (v >> (sizeof(int) * CHAR_BIT - 1));  // -1, 0, or +1
// Or, for portability, brevity, and (perhaps) speed:
sign = (v > 0) - (v < 0); // -1, 0, or +1

// If instead you want to know if something is non-negative, resulting in +1
// or else 0, then use:

sign = 1 ^ ((unsigned int)v >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then 0, else 1

// Caveat: On March 7, 2003, Angus Duggan pointed out that the 1989 ANSI C
// specification leaves the result of signed right-shift implementation-defined,
// so on some systems this hack might not work. For greater portability, Toby
// Speight suggested on September 28, 2005 that CHAR_BIT be used here and
// throughout rather than assuming bytes were 8 bits long. Angus recommended
// the more portable versions above, involving casting on March 4, 2006.
// Rohit Garg suggested the version for non-negative integers on September 12, 2009. 

Ответ 4

Или вы можете использовать signbit() и работу, выполненную для вас.

Я предполагаю, что под капотом реализация math.h - эффективная побитовая проверка (возможно, решение вашей исходной цели).

Ссылка: http://en.cppreference.com/w/cpp/numeric/math/signbit

Ответ 5

#include<stdio.h>

void main()
{
    int n;  // assuming int to be 32 bit long

    //shift it right 31 times so that MSB comes to LSB position
    //and then and it with 0x1
    if ((n>>31) & 0x1 == 1) {
        printf("negative number\n");
    } else {
        printf("positive number\n");
    }

    getch();
}

Ответ 6

Подписанные целые числа и плавающие точки обычно используют самый старший бит для хранения знака, поэтому, если вы знаете размер, вы можете извлечь информацию из наиболее значимого бита.

В этом, как правило, мало пользы, поскольку для использования этой информации необходимо будет провести какое-то сравнение, и для процессора так же легко проверить, что-то отрицательно, поскольку оно проверяет, не является ли оно нуль. Если факт на процессорах ARM, проверка наиболее значимого бита будет, как правило, БОЛЕЕ дороже, чем проверка того, является ли он отрицательным.

Ответ 7

Это довольно просто

Это легко сделать с помощью

return ((!!x) | (x >> 31));

он возвращает

  • 1 для положительного числа,
  • -1 для отрицательного значения и
  • 0 для нуля

Ответ 8

// if (x < 0) return -1
// else if (x == 0) return 0
// else return 1
int sign(int x) {
  // x_is_not_zero = 0 if x is 0 else x_is_not_zero = 1
  int x_is_not_zero = (( x | (~x + 1)) >> 31) & 0x1;
  return (x & 0x01 << 31) >> 31 | x_is_not_zero; // for minux x, don't care the last operand 
}

Вот именно то, что вы waht!

Ответ 9

Это невозможно сделать переносимым способом с битовыми операциями в C. Представления для целочисленных типов со знаком, которые допускает стандарт, могут быть намного более странными, чем вы могли бы подозревать. В частности, значение с битом знака включено и в противном случае нулевое значение не обязательно должно быть допустимым значением для подписанного типа или неподписанного типа, а так называемое ловушечное представление для обоих типов.

Все вычисления с битовыми операторами, которые вы можете таким образом сделать, могут иметь результат, который приводит к поведению undefined.


В любом случае, как показывают некоторые другие ответы, это не является необходимым, и сравнение с < или > должно быть достаточным в любом практическом контексте, более эффективно, проще читать... так что просто сделайте это таким образом.

Ответ 10

if( (num>>sizeof(int)*8 - 1) == 0 )
    // number is positive
else
   // number is negative

Если значение равно 0, тогда число положительное, другое отрицательное

Ответ 11

Более простой способ выяснить, является ли число положительным или отрицательным: Пусть число равно x проверьте, есть ли [x * (-1)] > x. если истина x отрицательна, то положительная.

Ответ 12

Вы можете различать отрицательный/неотрицательный, глядя на самый старший бит. Во всех представлениях для целых чисел со знаком этот бит будет установлен в 1, если число отрицательно.

Нет никакого теста, чтобы различать нуль и положительный, за исключением прямого теста против 0.

Чтобы проверить отрицательный результат, вы можете использовать

#define IS_NEGATIVE(x) ((x) & (1U << ((sizeof(x)*CHAR_BIT)-1)))

Ответ 13

Предположим, что ваш номер a=10 (положительный). Если вы сдвинете a a раз, он даст нуль.

то есть:

10>>10 == 0

Итак, вы можете проверить, положительно ли это число, но в случае a=-10 (отрицательный):

-10>>-10 == -1

Итак, вы можете комбинировать те, которые находятся в if:

if(!(a>>a))
   print number is positive
else 
   print no. is negative 

Ответ 14

Если вы уверены в размере целого числа (предполагая 16-битный int):

bool is_negative = (unsigned) signed_int_value >> 15;

Если вы не уверены в размере целых чисел:

bool is_negative = (unsigned) signed_int_value >> (sizeof(int)*8)-1; //where 8 is bits

Ключевое слово unsigned не является обязательным.