http://qs321.pair.com?node_id=205855

KPeter0314 has asked for the wisdom of the Perl Monks concerning the following question:

As I am just a lowly monk, I come to the greater wisdom of the group.

I have a set of values that I would like to possibly store in a binary-style array. The data looks something like this:

Slot 0 1 2 3 4 5 6 7 Value A A B B C C B B
Is there a way to store the values binary-style? That way the values for A, B, and C would be 11000000, 00110011, and 00001100 respectfully.

I would also need a method to mask the info back out of the binary storage to get my results back. e.g. (in bad pseudo-code)

if ( mask 01000000 matches arrayA )
then A is slot 1

Or, am I trying too hard?

-Kurt

Replies are listed 'Best First'.
Re: Binary data type?
by tadman (Prior) on Oct 17, 2002 at 00:29 UTC
    As others have mentioned, what you want is probably vec, but you'll have to be careful how you use it. Here's an example on how to convert from your regular input array to a hash of binary sequences. As a note, 0bN is the binary value "N", just like 0xN is the hexadecimal one:
    my @slot = qw[ A A B B C C B B ]; my %slot_mask; # Create a hash based on the input names. Each hash entry # contains a single binary sequence for the "slot" numbers # that are specified earliner in @slot foreach (0..$#slot) { # Create a "blank" scalar if none is defined already unless (defined($slot_mask{$slot[$_]}) { $slot_mask{$slot[$_]} = ''; } # Set this particular bit to 1 using an assignment vec($slot_mask{$slot[$_]}, $_, 1) = 1; } # Retrieval, as per your example, for the 1st slot if ($slot_mask{A} & 0b00000010) { print "1st is A...\n"; } # Same idea but with the shift operator that is less prone # to typographical errors if ($slot_mask{A} & (1 << 1)) { print "1st is A...\n"; } # And likewise for the 4th or what have you, but this time # using the vec() function if (vec($slot_mask{A}, 4, 1)) { print "4th is A...\n"; }
    I'm not sure of what the utility of such a thing would be, though. You might be chasing a data structure with little practical value. This is probably what you mean by "trying too hard."

    As a note, comparing to 0bN values is probably a bad idea if you have a large number of "slots", such as more than 31, as you'll be using numbers outside the typical range of your run-of-the-mill 32-bit "int".

    As a note, in your example you specified A being 0b11000000, which is technically backwards. It is actually 0b00000011 since the 0th slot is on the conceptual right side, not the left, when counting bits.
Re: Binary data type?
by blakem (Monsignor) on Oct 16, 2002 at 21:46 UTC
Re: Binary data type?
by nothingmuch (Priest) on Oct 16, 2002 at 21:55 UTC
    As bit vectors have already been addressed, this is only in regard to masking.
    You will first need to construct a bitstring for the mask.

    my $mask = pack("b*","01000000");

    Will create a bitstring, least significant bit first, which is the order defined by vec(), with the appropriate mask. Next you supply a bitwise operator: & in your case.


    my $result = $mask & $array

    Finally, you must check the bit again with vec().

    if (vec($result,1,1)){ }; # A exists in slot 1

    Unless you've used integers instead of bitstrings, in which case unless all the bits are false the value will be true.

    -nuffin
    zz zZ Z Z #!perl
Re: Binary data type?
by thor (Priest) on Oct 16, 2002 at 23:40 UTC
    One thing that I notice right off of the bat is that you have three distinct values that you're trying to store. One bit is not sufficient for storage as it only has two states. You could use trinary, where each tit (bit is short for binary digit, so tit is short for trinary digit, I guess) could have values of 0, 1, or 2. Also, are conditions A, B, and C mutually exclusive? If not, then you need even more storage, as setting the tit for one value will clober what was there. I would advise against using tits, however, as you lose the usefullness of such operators as << and & for masking operations.

    thor

      The word you're looking for is "trit".

      __SIG__ printf "You are here %08x\n", unpack "L!", unpack "P4", pack "L!", B::svref_2object(sub{})->OUTSIDE;
Re: Binary data type?
by graff (Chancellor) on Oct 17, 2002 at 05:45 UTC
    Or, am I trying too hard?

    Could be... The only rationale for bit vectors these days, I think, would be when you have to stuff things into hardware registers or send binary codes over serial ports to control devices at something close to the level of a driver. If that's what you're after, then vec() is your friend.

    But if you're just trying to save space in memory, don't bother. Use plain integers and letters in a hash or simple array, and you'll get done a lot quicker with fewer mishaps.

      After more meditation I seem to have come to the same conclusion. An array (hashed or not...) is probably a better way to go for a couple of reasons.
      1. It can contain more that a trit. ;-)
      2. I can easily avoid assigning duplicates to the same slot.
      3. Arrays are relatively easy to deal with.
      4. Quicker to write.
      I was just having a flashback to my computer science college days and thinking about other ways to store the data. I wouldn't mind dealving into the vec() bitwise operations evenutally, but I think I have convinced myself otherwise for this project.