Проверка того, является ли число положительным или отрицательным с помощью побитовых операторов
Я могу проверить, является ли число нечетным/четным с помощью побитовых операторов. Могу ли я проверить, является ли число положительным/нулевым/отрицательным, без использования каких-либо условных операторов/операторов, например if/ternary и т.д.
Можно ли это сделать с помощью побитовых операторов и некоторого трюка в C или на С++?
Ответы
Ответ 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
не является обязательным.