extracting front bits from an unsigned long long?

Discussion in 'C Programming' started by Digital Puer, Nov 11, 2005.

  1. Digital Puer

    Digital Puer Guest

    Hi, suppose I have an unsigned long long. I would like to extract
    the front 'n' bits of this value and convert them into an integer.
    For example, if I extract the first 3 bits, I would get an int between
    0 and 7 (=2^3-1). Could someone please help out?

    I can assume the largest returned value fits in an int. Also,
    I'm on a big-endian PPC (AIX), in case that matters.

    Ideally, I'd like to implement a prototype like:
    int extractFrontBits(unsigned long long value, int num_bits);
    Digital Puer, Nov 11, 2005
    #1
    1. Advertising

  2. Digital Puer

    pete Guest

    Digital Puer wrote:
    >
    > Hi, suppose I have an unsigned long long. I would like to extract
    > the front 'n' bits of this value and convert them into an integer.
    > For example, if I extract the first 3 bits, I would get an int between
    > 0 and 7 (=2^3-1). Could someone please help out?


    int three_bits = long_long_value & 7;

    --
    pete
    pete, Nov 11, 2005
    #2
    1. Advertising

  3. Digital Puer

    Guest

    Digital Puer wrote:
    > Hi, suppose I have an unsigned long long. I would like to extract
    > the front 'n' bits of this value and convert them into an integer.
    > For example, if I extract the first 3 bits, I would get an int between
    > 0 and 7 (=2^3-1). Could someone please help out?
    >
    > I can assume the largest returned value fits in an int. Also,
    > I'm on a big-endian PPC (AIX), in case that matters.
    >
    > Ideally, I'd like to implement a prototype like:
    > int extractFrontBits(unsigned long long value, int num_bits);


    I'm guessing long long is 64 bits? Regardless, the following should
    work:

    frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;

    The masking at the end is to zero out the msb of the result since on
    some systems it doesn't get zeroed.

    If number of bits is not fixed, then it would look something like the
    following:

    frontbits = original_value >> (sizeof(long long) - num_bits);

    but the masking will get complicated.
    , Nov 11, 2005
    #3
  4. Digital Puer

    pete Guest

    wrote:
    >
    > Digital Puer wrote:
    > > Hi, suppose I have an unsigned long long. I would like to extract
    > > the front 'n' bits of this value and convert them into an integer.
    > > For example, if I extract the first 3 bits,
    > > I would get an int between
    > > 0 and 7 (=2^3-1). Could someone please help out?


    > I'm guessing long long is 64 bits? Regardless, the following should
    > work:


    > frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;


    You're getting 2 bits from the middle of the value.
    Anything & 3, ain't going to get you more than 2 bits.
    You shift the original value to the right
    and the low order bits disappear.

    --
    pete
    pete, Nov 11, 2005
    #4
  5. Digital Puer

    pete Guest

    pete wrote:
    >
    > Digital Puer wrote:
    > >
    > > Hi, suppose I have an unsigned long long. I would like to extract
    > > the front 'n' bits of this value and convert them into an integer.
    > > For example, if I extract the first 3 bits,
    > > I would get an int between
    > > 0 and 7 (=2^3-1). Could someone please help out?

    >
    > int three_bits = long_long_value & 7;


    n bits, ... hmm ...

    long_long_value & ((1ULL << n) - 1)

    --
    pete
    pete, Nov 11, 2005
    #5
  6. On 10 Nov 2005 16:59:21 -0800, "Digital Puer"
    <> wrote:

    >Hi, suppose I have an unsigned long long. I would like to extract
    >the front 'n' bits of this value and convert them into an integer.
    >For example, if I extract the first 3 bits, I would get an int between
    >0 and 7 (=2^3-1). Could someone please help out?
    >
    >I can assume the largest returned value fits in an int. Also,
    >I'm on a big-endian PPC (AIX), in case that matters.
    >
    >Ideally, I'd like to implement a prototype like:
    >int extractFrontBits(unsigned long long value, int num_bits);


    Shift the value in the variable to the right
    (sizeof(unsigned long long)*CHAR_BIT - n)
    bits. The result is the integer you requested.


    <<Remove the del for email>>
    Barry Schwarz, Nov 11, 2005
    #6
  7. "Digital Puer" <> writes:
    > Hi, suppose I have an unsigned long long. I would like to extract
    > the front 'n' bits of this value and convert them into an integer.
    > For example, if I extract the first 3 bits, I would get an int between
    > 0 and 7 (=2^3-1). Could someone please help out?


    What do you mean by "front" bits?

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Nov 11, 2005
    #7
  8. Digital Puer

    Guest

    pete wrote:
    > wrote:
    > >
    > > Digital Puer wrote:
    > > > Hi, suppose I have an unsigned long long. I would like to extract
    > > > the front 'n' bits of this value and convert them into an integer.
    > > > For example, if I extract the first 3 bits,
    > > > I would get an int between
    > > > 0 and 7 (=2^3-1). Could someone please help out?

    >
    > > I'm guessing long long is 64 bits? Regardless, the following should
    > > work:

    >
    > > frontbits = (original_value >> (sizeof(long long) - 3)) & 0x03;

    >
    > You're getting 2 bits from the middle of the value.
    > Anything & 3, ain't going to get you more than 2 bits.
    > You shift the original value to the right
    > and the low order bits disappear.
    >
    > --
    > pete


    Ah, sorry, it should be:

    frontbits = (original_value >> (sizeof(long long) - 3)) & 0x07;
    , Nov 11, 2005
    #8
  9. Digital Puer

    pete Guest

    wrote:
    >
    > pete wrote:
    > > wrote:
    > > >
    > > > Digital Puer wrote:
    > > > > Hi, suppose I have an unsigned long long.
    > > > > I would like to extract
    > > > > the front 'n' bits of this value and convert them
    > > > > into an integer.
    > > > > For example, if I extract the first 3 bits,
    > > > > I would get an int between
    > > > > 0 and 7 (=2^3-1). Could someone please help out?

    > >
    > > > I'm guessing long long is 64 bits?
    > > > Regardless, the following should
    > > > work:

    > >
    > > > frontbits =
    > > > (original_value >> (sizeof(long long) - 3)) & 0x03;

    > >
    > > You're getting 2 bits from the middle of the value.
    > > Anything & 3, ain't going to get you more than 2 bits.
    > > You shift the original value to the right
    > > and the low order bits disappear.


    > Ah, sorry, it should be:
    >
    > frontbits = (original_value >> (sizeof(long long) - 3)) & 0x07;


    Barry Schwarz also seems to think that shifting the original
    value to the right, is the right thing to do.
    I don't get it.

    I'll assume you think that CHAR_BIT is 8.
    That makes your 64 bit bit long long, 8 bytes in size.
    8 - 3 is two, so you shift your unsigned long long
    two bits to the right, which is equivalent to dividing by 4,
    and then you take the 3 lower order bits.
    What is that?

    --
    pete
    pete, Nov 11, 2005
    #9
  10. Digital Puer

    pete Guest

    Digital Puer wrote:
    >
    > Hi, suppose I have an unsigned long long. I would like to extract
    > the front 'n' bits of this value and convert them into an integer.
    > For example, if I extract the first 3 bits, I would get an int between
    > 0 and 7 (=2^3-1). Could someone please help out?
    >
    > I can assume the largest returned value fits in an int. Also,
    > I'm on a big-endian PPC (AIX), in case that matters.
    >
    > Ideally, I'd like to implement a prototype like:
    > int extractFrontBits(unsigned long long value, int num_bits);


    int extractFrontBits(unsigned long long value, int num_bits)
    {
    return (int)(value & ((1ULL << num_bits) - 1))
    }

    --
    pete
    pete, Nov 11, 2005
    #10
  11. Digital Puer

    Guest

    pete wrote:
    > I'll assume you think that CHAR_BIT is 8.
    > That makes your 64 bit bit long long, 8 bytes in size.
    > 8 - 3 is two, so you shift your unsigned long long
    > two bits to the right, which is equivalent to dividing by 4,
    > and then you take the 3 lower order bits.
    > What is that?
    >


    Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
    part.


    > Barry Schwarz also seems to think that shifting the original
    > value to the right, is the right thing to do.
    > I don't get it.
    >


    I think he's also a hardware guy, the first few bits to us are the msb.
    We feel last (as in last few bits) and least (as in lsb) are
    equivalent. So it follows that first and most are equivalent.

    BTW, does C make any guarantees that the code works both endianness? I
    have worked with compilers where shifting didn't do what I expected
    because the machine was little endian. The OP would not have this
    problem since he's running AIX on what I assume is either Power or
    PowerPC.

    Hardware guys tend to think in big-endian while software guys tend to
    be little-endian. We like things big :)
    , Nov 11, 2005
    #11
  12. Digital Puer

    Suman Guest

    pete wrote:

    > I'll assume you think that CHAR_BIT is 8.
    > That makes your 64 bit bit long long, 8 bytes in size.
    > 8 - 3 is two, ...


    [ ...]

    > What is that?


    Exactly! Beats me.
    Suman, Nov 11, 2005
    #12
  13. Barry Schwarz wrote:
    > "Digital Puer" <> wrote:
    > >Hi, suppose I have an unsigned long long. I would like to extract
    > >the front 'n' bits of this value and convert them into an integer.
    > >For example, if I extract the first 3 bits, I would get an int between
    > >0 and 7 (=2^3-1). Could someone please help out?
    > >
    > >I can assume the largest returned value fits in an int. Also,
    > >I'm on a big-endian PPC (AIX), in case that matters.
    > >
    > >Ideally, I'd like to implement a prototype like:
    > >int extractFrontBits(unsigned long long value, int num_bits);

    >
    > Shift the value in the variable to the right


    The OP hasn't said what 'front' bits are, but...

    > (sizeof(unsigned long long)*CHAR_BIT - n)
    > bits. The result is the integer you requested.


    That assumes that unsigned long long isn't padded. The following
    doesn't...

    value / ((-1ull >> num_bits) + 1)

    ....although it does assume that num_bits is non-zero and less than the
    width of unsigned
    long long.

    --
    Peter
    Peter Nilsson, Nov 11, 2005
    #13
  14. Digital Puer

    Jack Klein Guest

    On 10 Nov 2005 20:38:54 -0800, ""
    <> wrote in comp.lang.c:

    > pete wrote:
    > > I'll assume you think that CHAR_BIT is 8.
    > > That makes your 64 bit bit long long, 8 bytes in size.
    > > 8 - 3 is two, so you shift your unsigned long long
    > > two bits to the right, which is equivalent to dividing by 4,
    > > and then you take the 3 lower order bits.
    > > What is that?
    > >

    >
    > Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
    > part.
    >
    >
    > > Barry Schwarz also seems to think that shifting the original
    > > value to the right, is the right thing to do.
    > > I don't get it.
    > >

    >
    > I think he's also a hardware guy, the first few bits to us are the msb.
    > We feel last (as in last few bits) and least (as in lsb) are
    > equivalent. So it follows that first and most are equivalent.
    >
    > BTW, does C make any guarantees that the code works both endianness? I
    > have worked with compilers where shifting didn't do what I expected
    > because the machine was little endian. The OP would not have this
    > problem since he's running AIX on what I assume is either Power or
    > PowerPC.


    I don't know what you expected, or what you did, but shifts of
    unsigned types in C are defined by value, and are completely
    independent of endianness. This assumes the shift amount is not less
    than 0 and is less than the width of the unsigned type in bits.

    Given unsigned long l = 0x12345678, then:

    l & 0xff is 0x78
    (l >> 8) & 0xff is 0x56
    (l >> 16) & 0xff is 0x34
    (l >> 24) & 0xff is 0x12

    Shifting unsigned types in C is always exactly defined, and has
    nothing at all to do with endianness. Your problem was caused by
    something else.

    > Hardware guys tend to think in big-endian while software guys tend to
    > be little-endian. We like things big :)


    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Nov 11, 2005
    #14
  15. Digital Puer

    Guest

    Jack Klein wrote:
    > I don't know what you expected, or what you did, but shifts of
    > unsigned types in C are defined by value, and are completely
    > independent of endianness. This assumes the shift amount is not less
    > than 0 and is less than the width of the unsigned type in bits.
    >
    > Given unsigned long l = 0x12345678, then:
    >
    > l & 0xff is 0x78
    > (l >> 8) & 0xff is 0x56
    > (l >> 16) & 0xff is 0x34
    > (l >> 24) & 0xff is 0x12
    >
    > Shifting unsigned types in C is always exactly defined, and has
    > nothing at all to do with endianness. Your problem was caused by
    > something else.
    >


    OK, that's what I'd expect. But, does

    0x12345678 == 305419896

    or

    0x12345678 == 2018915346

    If the number is in hex and output in hex then of course it always
    works. But I was expecting something like:

    (305419896 >> 16) & 0xff == 52


    Maybe its just the compiler I was using since it works fine in gcc. I
    expect fully conforming compilers treats hex numbers as real
    "big-endian" representation of a number.
    , Nov 11, 2005
    #15
  16. Digital Puer

    Michael Mair Guest

    wrote:
    > Jack Klein wrote:
    >
    >>I don't know what you expected, or what you did, but shifts of
    >>unsigned types in C are defined by value, and are completely
    >>independent of endianness. This assumes the shift amount is not less
    >>than 0 and is less than the width of the unsigned type in bits.
    >>
    >>Given unsigned long l = 0x12345678, then:
    >>
    >> l & 0xff is 0x78
    >> (l >> 8) & 0xff is 0x56
    >> (l >> 16) & 0xff is 0x34
    >> (l >> 24) & 0xff is 0x12
    >>
    >>Shifting unsigned types in C is always exactly defined, and has
    >>nothing at all to do with endianness. Your problem was caused by
    >>something else.

    >
    > OK, that's what I'd expect. But, does
    >
    > 0x12345678 == 305419896
    >
    > or
    >
    > 0x12345678 == 2018915346
    >
    > If the number is in hex and output in hex then of course it always
    > works.


    No! It _always_ works.
    In base B, the number represented by the digits
    n_k n_{k-1} ... n_0
    always means n_0 * B^0 + n_1 * B^1 + ... + n_k * B^k,
    so 0x12345678 clearly is 8 + 7*16 + ... = 305419896
    As 0x... means unsigned, we have a guarantee how the internal
    representation will look, i.e. the above _always_ works

    > But I was expecting something like:
    >
    > (305419896 >> 16) & 0xff == 52


    So what? 0x34 == 52U

    > Maybe its just the compiler I was using since it works fine in gcc. I
    > expect fully conforming compilers treats hex numbers as real
    > "big-endian" representation of a number.


    Whatever this is supposed to mean for machines with CHAR_BIT == 18
    and hexadecimal numbers.

    -Michael
    --
    E-Mail: Mine is an /at/ gmx /dot/ de address.
    Michael Mair, Nov 11, 2005
    #16
  17. Digital Puer

    CoL Guest

    Digital Puer wrote:
    > Hi, suppose I have an unsigned long long. I would like to extract
    > the front 'n' bits of this value and convert them into an integer.
    > For example, if I extract the first 3 bits, I would get an int between
    > 0 and 7 (=2^3-1). Could someone please help out?
    >
    > I can assume the largest returned value fits in an int. Also,
    > I'm on a big-endian PPC (AIX), in case that matters.
    >
    > Ideally, I'd like to implement a prototype like:
    > int extractFrontBits(unsigned long long value, int num_bits);


    Try this I think this solves your problem.

    unsigned long int original_value=0xffffffff; //could be what ever
    int frontbits=0;
    int n=3; //suppose we want to extract front 3 bits
    frontbits = (original_value >> (sizeof(long int )*8 - n)) & -1;

    This works fine on all machines(e.g intel series, sparc, powerpc) which
    use 2's complement represent negative numbers.

    Regards,
    Apoorv
    CoL, Nov 11, 2005
    #17
  18. Digital Puer

    Guest

    Michael Mair wrote:
    > No! It _always_ works.


    If the compiler follows C standards. As I said before, I HAVE used a
    compiler where this is not the case. But that is outside the scope of
    c.l.c of course.


    > > But I was expecting something like:
    > >
    > > (305419896 >> 16) & 0xff == 52

    >
    > So what? 0x34 == 52U


    Yes. That's what I expected. What's with your "so what" ?
    , Nov 11, 2005
    #18
  19. Digital Puer

    pete Guest

    wrote:
    >
    > pete wrote:
    > > I'll assume you think that CHAR_BIT is 8.
    > > That makes your 64 bit bit long long, 8 bytes in size.
    > > 8 - 3 is two, so you shift your unsigned long long
    > > two bits to the right, which is equivalent to dividing by 4,
    > > and then you take the 3 lower order bits.
    > > What is that?
    > >

    >
    > Sorry again, Barry got it right, multiply with CHAR_BIT. I forgot that
    > part.
    >
    > > Barry Schwarz also seems to think that shifting the original
    > > value to the right, is the right thing to do.
    > > I don't get it.
    > >

    >
    > I think he's also a hardware guy,
    > the first few bits to us are the msb.
    > We feel last (as in last few bits) and least (as in lsb) are
    > equivalent. So it follows that first and most are equivalent.


    If Value is the identifier of an object
    declared as usigned long long and you wanted to see if
    Value was odd, it would be (Unsigned_Value & 1).
    Where bits and bytes of the object are stored
    has got nothing to do with it.

    --
    pete
    pete, Nov 11, 2005
    #19
  20. Digital Puer

    pete Guest

    Suman wrote:
    >
    > pete wrote:
    >
    > > I'll assume you think that CHAR_BIT is 8.
    > > That makes your 64 bit bit long long, 8 bytes in size.
    > > 8 - 3 is two, ...

    >
    > [ ...]
    >
    > > What is that?

    >
    > Exactly! Beats me.


    I should have used a calculator.

    --
    pete
    pete, Nov 11, 2005
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. George Marsaglia

    Assigning unsigned long to unsigned long long

    George Marsaglia, Jul 8, 2003, in forum: C Programming
    Replies:
    1
    Views:
    662
    Eric Sosman
    Jul 8, 2003
  2. sarmin kho
    Replies:
    2
    Views:
    820
    A. Lloyd Flanagan
    Jun 15, 2004
  3. Miki Tebeka
    Replies:
    1
    Views:
    435
    Marcin 'Qrczak' Kowalczyk
    Jun 14, 2004
  4. krunalb
    Replies:
    10
    Views:
    900
    Kenneth Brody
    Jan 23, 2007
  5. pozz
    Replies:
    12
    Views:
    726
    Tim Rentsch
    Mar 20, 2011
Loading...

Share This Page