1

I searched online and the common solution for returning x bits from start seems to be:

mask = ((1 << x) - 1 ) << start

then, mask & value.

However, I'm confused on how this works still.

If I have a number 0101 1100 and I want to return the two bits from positions 5 and 6 (11)

mask = ((1<<2)-1) << 5

1<<2 = 0000 0100, and subtracting 1 yields 0000 0011 then, shifting 5 is 0110 0000

If I take 0110 0000 & 0101 1100 (the original), I get 0100 0000

This is not the answer I want, so what am I doing wrong?

Pablo
  • 13,271
  • 4
  • 39
  • 59
sy89
  • 195
  • 2
  • 14

4 Answers4

3

Assuming we're referring to two's complement binary, then 11 would be bits 2 and 3 (or 3 and 4, depending on who you ask).

Think of it this way. If you want to get a specific amount of bits from the middle of a binary value, then you can first shift it to the right n times where n is the index of the first bit of interest.

Shifting 0101 1100 to the right twice yields 0001 0111

Here, we're interested in the first two bits, so we can simply call 0001 0111 & 3 because 3 = 00000011.

Therefore, the formula for this specific example is (b >> 2) & 3 where b is the binary value.

If you want the value at their current location, you can call 0101 1100 & 12 because 12 = 00001100, which returns 0000 1100.

Jacob G.
  • 28,856
  • 5
  • 62
  • 116
  • Endian-ness is about byte ordering, not bit ordering. Bit zero is always the least significant bit. So no assumption about big-endian is necessary. – Clifford Jan 27 '18 at 17:58
  • @Clifford True, I must have been thinking of two's complement instead. – Jacob G. Jan 27 '18 at 17:59
  • I am not sure that 2's complement is relevant either; bitwise operations are normally performed unsigned types - it is just bit patterns. In particular the behaviour of `>>` is undefined for negative values. Counting from zero makes much more sense, because then for example in `1< – Clifford Jan 27 '18 at 18:07
  • @Clifford, I agree that numbering bits starting from the least significant bit is most common, even on big endian computers. But the PowerPC numbers bits starting at the most significant bit. Wikipedia says this is true of the S/390 and PA-RISC also. – Doug Currie Jan 27 '18 at 18:14
  • Without a link I cannot comment on what you are reading, but I suspect that such numbering relates only to the manufacturer's hardware specification and documentation. In C language code it makes little sense to number the MSB bit zero or either LSB or MSB bit one. Apart from that the MSB being zero would not make "_or 3 and 4_" correct - that is merely about numbering from 1 not zero. I have seen datasheets for electronic components that start bit numbering form 1 [MB1507 frequency synthesizer](http://www.om3bc.com/datasheets/MB1507.pdf) for example, so conventions vary in other domains. – Clifford Jan 27 '18 at 18:28
  • The point is the following the convention LSB = bit zero, the code in the question works as expected regardless of the hardware architecture - it is entirely portable, so any discussion of bit-ordering or LSB number is irrelevant - the convention used in the code is LSB = bit 0; that is really all you need to know. – Clifford Jan 27 '18 at 18:31
1

Bit positions are typically counted from least- to most-significant, i.e. right-to-left.

0101 1110
---- ----
7654 3210

The bits you want are bits 2 and 3.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
0

for e.g input num is 92 = 0101 1100 initial pos = 1 ending pos = 4

Now your task is to find the number b/w 1st and 4th position(LSB to MSB), output should be 11 means 3.

First find the no of ones b/w these 2 positions, for this rotate loop from starting position to ending position and do

sum = sum | 1<<i; // sum =12( 1100)

Next if you do sum & num, you will get output b/w given positions which is 1100 but you need 11 so do 1100 >> 2(which is n1+1)

Here is the my solution

   int sum = 0,num,res; /** num is your input number **/
   for(int i=n1+1;i<n2;i++) /* n1 is starting position and n2 is the ending position */
            sum = sum | (1<<i); //counting ones
    res = sum & num; // we will get o/p in middle 
    res = res>>(n1+1); // shift previous res to correct position

Finally prints the res.

Achal
  • 11,821
  • 2
  • 15
  • 37
  • The question was not about a solution, but rather understanding the solution. This is a vastly over complex solution in any case. – Clifford Jan 27 '18 at 18:01
  • @Clifford It's a simplest solution. – Achal Jan 27 '18 at 18:07
  • The question contains a solution that is far simpler (and the means by which any reasonable developer would perform this operation). But that is missing my point; the question is about how it works, not an alternative and less efficient solution. The only reasons the OP did not understand how it worked because he was assuming bits numbers from MSB first and starting from 1. – Clifford Jan 27 '18 at 18:11
0

As advised by many, you should start your positioning from the right.

   num =   0101 1100
Positions: 8765 4321

Then the given solution work's just fine.


However, a more detailed approach by myself would be:

To get the values of the bits at position 3 and 4 ('11'), I would do the following:

Let's say you want the bit at position k. Shift a 1, k-1 positions to the left and evaluate it with the &-operator. Shift it back, then save the result in an array with the length of how many bits you want. Repeat the process for the rest.

int mask = 1 << (k - 1);
int bitAtPosK = (num & mask) >> (k - 1);

... do this in a loop and save the results.

Visualisation for Position 3:

num = 0101 1100
1 << 2 results in 0000 0010

and
0101 1100
0000 0100
--------- &
0000 0100

0000 0100 >> 2 results in 1
J. Wu
  • 69
  • 1
  • 1
  • 7