extracting front bits from an unsigned long long?

D

Digital Puer

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);
 
P

pete

Digital said:
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;
 
S

slebetman

Digital said:
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.
 
P

pete

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.
 
B

Barry Schwarz

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>>
 
K

Keith Thompson

Digital Puer said:
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?
 
S

slebetman

pete said:
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;
 
P

pete

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?
 
P

pete

Digital said:
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))
}
 
S

slebetman

pete said:
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 :)
 
P

Peter Nilsson

Barry said:
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.
 
J

Jack Klein

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



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.
 
S

slebetman

Jack said:
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.
 
M

Michael Mair

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
 
C

CoL

Digital said:
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
 
S

slebetman

Michael said:
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.

So what? 0x34 == 52U

Yes. That's what I expected. What's with your "so what" ?
 
P

pete

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


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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top