Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine which bit is set in an unsigned int64

I have a variable vBit which is an unsigned int64. I know there is exactly one bit set, and I need to figure out which one it is. Currently I do it like this (in Delphi):

vPos := -1;
repeat
  vBit := vBit shr 1;
  inc(vPos);
until vBit = 0;

Is there a faster way? All bit positions are equally likely, so on average the algorithm needs to iterate 32 times. I am looking for an elegant trick with ands and xors and whatnot.

like image 710
Svein Bringsli Avatar asked Jan 08 '10 11:01

Svein Bringsli


People also ask

How do you check bit is set or not?

Method 1 (Using Left Shift Operator) 1) Left shift given number 1 by k-1 to create a number that has only set bit as k-th bit. temp = 1 << (k-1) 2) If bitwise AND of n and temp is non-zero, then result is SET else result is NOT SET.

How do you set a bit in a number?

Setting a bitUse the bitwise OR operator ( | ) to set a bit. number |= 1UL << n; That will set the n th bit of number . n should be zero, if you want to set the 1 st bit and so on upto n-1 , if you want to set the n th bit.

Can any unsigned number be represented using one register in 64 bit processor?

It can be 18446744073709551615 . Show activity on this post. Your assumption for the maximum size of signed and unsigned integers is correct. The actual values are 9223372036854775807 for signed and 18446744073709551615 for unsigned.

How high can a 64 bit integer be?

A 64-bit signed integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive).


2 Answers

Finding the first bit set is the same as counting the zero bits, so this hack might help. That's a really useful page to bookmark, by the way.

like image 173
Bob Moore Avatar answered Sep 30 '22 15:09

Bob Moore


You might do an and with $FFFFFFFF00000000 and if it is non zero add 32 next you and with $FFFF0000FFFF0000 and if non zero, add 16 etc etc. In the end you have your answer and it is very fast:

Result := Ord( ( Val and $FFFFFFFF00000000 ) <> 0 ) * 32 +
          Ord( ( Val and $FFFF0000FFFF0000 ) <> 0 ) * 16 +
          Ord( ( Val and $FF00FF00FF00FF00 ) <> 0 ) * 8 +
          Ord( ( Val and $F0F0F0F0F0F0F0F0 ) <> 0 ) * 4 +
          Ord( ( Val and $CCCCCCCCCCCCCCCC ) <> 0 ) * 2 +
          Ord( ( Val and $AAAAAAAAAAAAAAAA ) <> 0 );

This works only if a single bit is set!

Note: I did not test the routine shown above.

like image 33
Ritsaert Hornstra Avatar answered Sep 30 '22 16:09

Ritsaert Hornstra