2

recently I was doing something related to bit manipulation. Up until now, I've tried many bit manipulations operations. But I am stuck at one operation.

Suppose I have int n = 5; binary (101), Now I would like to perform bitwise NOT on this int which I thought of the result would be (010) but rather the result was -6.

But when I tried n = ~(-n) it gave me the result 4 (Although still didn't get the right output). Please tell why is it showing this type of behaviour is it because my int is not unsigned. Also please tell me the perfect way to implement the operation so I can get the right output. My main motive is to flip the bits correctly.

Thank you

13
  • 1
    An int has more than 3 bits. One of them happens to be the sign-bit as you correctly guessed. What is "the perfect way to implement the operation"? Do you want to implement bitwise not yourself? What operation do you want to implement and what is not perfect now? Commented Jun 11, 2020 at 7:01
  • 1
    Hint: n = 5 contains a load of leading zeros (the number depends on the size of your int). You are setting those leading zeros to 1 in your output. Commented Jun 11, 2020 at 7:01
  • @churill I just simply want to implement NOT operation like (101) -> (010) Commented Jun 11, 2020 at 7:02
  • 2
    You need to first find the most signficant set bit, construct a mask from that then do the negation and finally mask out the top bits. Your question is not clear and hence you are getting answers for exactly 3 bits which is probably not what you want. Commented Jun 11, 2020 at 7:08
  • 1
    @VaibhavBisht - You'll have to work out how many bits are set, and then only flip those bits. That's involves more than the ~ operator. You'll also need to be careful on handling the sign bit (elements of unspecified or implementation-defined [don't recall which offhand] behaviour on negative values). Also, unlike ~, it means that applying your approach twice won't necessarily give back the original value (101 -> 010 -> 001). Commented Jun 11, 2020 at 7:13

3 Answers 3

3

int has more than tree bits, so you must mask the result of a bitwise negation like this:

int flip(int n) { // bitwise AND with 0b111 = 7, this will clear all but the last 3 bits return ~n & 0b111; } 

The reason you got -6 is because int is typically represented in two's complement, where -6 is all 1-bits but ends with 010. You must remove these leading 1-bits to get the correct result.

Generally, I would recommend not using bitwise operations with signed numbers and instead do the following:

unsigned flip(unsigned n) { return ~n & 0b111; } // this version works with any number of bits, not just 3 unsigned flip(unsigned n, unsigned bits) { unsigned mask = (1 << bits) - 1; return ~n & mask; } 

If you don't know how many bits your number has, you must first find the most significant bit. In the most naive way, it can be done like this:

unsigned log2(unsigned val) { unsigned result = 0; while (val >>= 1) { ++result; } return result; } unsigned variable_flip(unsigned n) { return flip(n, log2(n)); } 

You can find more efficient solutions here.

For example:

unsigned log2_debruijn(uint32_t val) { static const unsigned MultiplyDeBruijnBitPosition[32] = {0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31}; // first round down to one less than a power of 2 // this step is not necessary if val is a power of 2 val |= val >> 1; val |= val >> 2; val |= val >> 4; val |= val >> 8; val |= val >> 16; return MultiplyDeBruijnBitPosition[(val * uint32_t{0x07C4ACDD}) >> 27]; } 
Sign up to request clarification or add additional context in comments.

12 Comments

what is 0b111 it's not a hexadecimal value. What is it? And why are performing AND(&) operation with it??
@VaibhavBisht 0b111 is a binary value, it's the same as 0x7 which is hexadecimal or 7 which is decimal.
@Jabberwocky but why are we only performing and (&) operation with 7
@VaibhavBisht Because you did not make it clear in your question that you want a general algorithm to handle variable bit widths.
@VaibhavBisht because the number 5 has 3 significant bits. This arrticle might be interesting for you: stackoverflow.com/questions/31393100/…
|
3

You probably want this:

// assuming n is a 32 bit int n = 5; // n = 00000000000000000000000000000101 n = ~n; // n = 11111111111111111111111111111010 n = n & 0x7; // n = 00000000000000000000000000000010 

With the & operator (bitwise and) you mask the bits 3 to 31 of n

you can of course contract the two last statements into one:

n = ~n & 0x7; 

Comments

2

First you need to find the most significant bit. You can do this by shifting right by 1 until you hit zero, counting how many times you shift.

unsigned int bit = 0; unsigned int tmp = n; while (tmp) { tmp >>= 1; bit++; 

Then shift the value 1 right that many bits, giving you a value of n rounded up to the nearest power of 2, then subtract 1 to get a mask with all bits below that value set:

unsigned int mask = (1U << bit) - 1; 

Then XOR it with your value to flip the bits set in the mask:

n = n ^ mask; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.