Checking whether a number is positive or negative using bitwise operators

后端 未结 16 796
轮回少年
轮回少年 2020-12-08 20:01

I can check whether a number is odd/even using bitwise operators. Can I check whether a number is positive/zero/negative without using any conditional statements/operators l

相关标签:
16条回答
  • 2020-12-08 20:11

    You can differentiate between negative/non-negative by looking at the most significant bit. In all representations for signed integers, that bit will be set to 1 if the number is negative.

    There is no test to differentiate between zero and positive, except for a direct test against 0.

    To test for negative, you could use

    #define IS_NEGATIVE(x) ((x) & (1U << ((sizeof(x)*CHAR_BIT)-1)))
    
    0 讨论(0)
  • 2020-12-08 20:13

    When you're sure about the size of an integer (assuming 16-bit int):

    bool is_negative = (unsigned) signed_int_value >> 15;
    

    When you are unsure of the size of integers:

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

    The unsigned keyword is optional.

    0 讨论(0)
  • 2020-12-08 20:14

    If the high bit is set on a signed integer (byte, long, etc., but not a floating point number), that number is negative.

    int x = -2300;  // assuming a 32-bit int
    
    if ((x & 0x80000000) != 0)
    {
        // number is negative
    }
    

    ADDED:

    You said that you don't want to use any conditionals. I suppose you could do this:

    int isNegative = (x & 0x80000000);
    

    And at some later time you can test it with if (isNegative).

    0 讨论(0)
  • 2020-12-08 20:18

    It is quite simple

    It can be easily done by

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

    it returns

    • 1 for a positive number,
    • -1 for a negative, and
    • 0 for zero
    0 讨论(0)
  • 2020-12-08 20:19

    Suppose your number is a=10 (positive). If you shift a a times it will give zero.

    i.e:

    10>>10 == 0
    

    So you can check if the number is positive, but in case a=-10 (negative):

    -10>>-10 == -1
    

    So you can combine those in an if:

    if(!(a>>a))
       print number is positive
    else 
       print no. is negative 
    
    0 讨论(0)
  • 2020-12-08 20:21

    There is a detailed discussion on the Bit Twiddling Hacks page.

    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. 
    
    0 讨论(0)
提交回复
热议问题