good chemistry is complicated,and a little bit messy -LW PerlMonks

### Which bit is set? (inverse of (1<<\$value) operator)

by wirito (Acolyte)
 on Sep 17, 2012 at 11:04 UTC Need Help??
wirito has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks, I'm storing values in a bitwise manner for speed up comparations. I can have 0 or more values in the 0..8 range, so I can store it this way:
```\$bits |= (1<<\$val)
When 1 single bit is set I want to retrive the original \$val. So currently I have this implemented:
```if( unpack( "%16B*", pack("n", \$bits)) == 1 ) {
my \$ret = 0;
while (!(\$bits & 0x1)) {
\$ret++;
\$bits >>= 1;
};
return \$ret;
};
I don't know why, but the while loop seems ugly. Could you enligthen me with a more perlish way to do this? PS: I hope the title is not so much confusing.

Replies are listed 'Best First'.
Re: Which bit is set? (inverse of (1<<\$value) operator)
by BrowserUk (Pope) on Sep 17, 2012 at 11:27 UTC

1. If only 1-bit will ever be set:

Use a lookup table:

```%lookup = map{ 2**\$_ => \$_ } 0 .. 63;;

\$flags = 0;;

\$flags |= 1<<(rand 64);;

print "The flag set is:", \$lookup{ \$flags };;
The flag set is: 12
2. If multiple flags can be set:

Some form of loop is necessary to avoid an impossibly large lookup table:

```\$flags = int rand( 2**64 );;

print for grep \$flags & 1 << \$_, 0 .. 63;;
49
50
51
54
55
57
58
59

printf "%u\n", \$flags;;
1066790161733386240

\$t = 0; print \$t += 1<<\$_ for  grep \$flags & 1 << \$_, 0 .. 63;;
562949953421312
1688849860263936
3940649673949184
21955048183431168
57983845202395136
202099033278251008
490329409429962752
1066790161733386240

With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.

Many thanks!

The lookup idea is nice and clean. I will use it as I only have 9 different bits.

However, your second option is the one I was (foolish) looking for. In my code, this could be the line:

```# return the first less significant bit set.
return \$_ for grep { \$bit & 1<<\$_ } (0..8)';
Re: Which bit is set? (inverse of (1<<\$value) operator)
by grizzley (Chaplain) on Sep 17, 2012 at 11:17 UTC
In description of unpack there is following method to count number of bits:
```# Count the bits in a chunk of memory (e.g. a select vector)
Update: sorry, I misunderstood question. If you have string of bits with one bit set, then you could try just \$bitstring =~ /1(0*)\$/; \$originalvalue = length(\$1)+1;
Nope, it's a two-byte int, not a strings filled with 0's and 1's.

Create A New User
Node Status?
node history
Node Type: perlquestion [id://994008]
Approved by Corion
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2018-01-22 01:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
How did you see in the new year?

Results (230 votes). Check out past polls.

Notices?