Paul
Paul

Reputation: 421

php - Bitmask "decode"

I would like to write a function to 'decode' bit mask into original values, e.g.
We have number and text attached to it:

Now I'm entering number e.g. 48 (32 + 16) and I should get Text_5 and Text_4 so it's should return two numbers: 32 and 16.
How to get this?

Upvotes: 0

Views: 826

Answers (3)

user1597430
user1597430

Reputation: 1146

I guess, this is the simplest and most "native" implementation:

$array = [2 => 'Text_1', 4 => 'Text_2', 8 => 'Text_3', 16 => 'Text_4', 32 => 'Text_5'];

$number = 48;

foreach ($array as $mask => $string)
{
    if ($number & $mask)
    {
        echo "$mask: $string" . PHP_EOL;
    }
}

Upvotes: 1

kiske
kiske

Reputation: 430

Another option using only bit operators...

unmaskMe(48);

function unmaskMe(int $bitset) {
    $bitOfsset = 0;

    while ($bitset) {
        if ($bitset & (1 << $bitOfsset)) {
            echo 'Text_' .  $bitOfsset . PHP_EOL;

            $bitset &= ~(1 << $bitOfsset);
        }

        $bitOfsset++;
    }
}

Outputs:

Text_4

Text_5

Upvotes: 0

lufc
lufc

Reputation: 2040

PHP has some functions to help with this, primarily decbin() (https://www.php.net/manual/en/function.decbin.php) which will convert an integer to binary. You can then break that up into an array which will be numbered by the Text_ values from your example.

$input = 48;
$output = array_reverse(str_split(decbin($input)));

foreach ($output as $k => $v) {
    echo $v ? "Text_$k".PHP_EOL : "";
}

So decbin(48) would give 110000, which you can break into the following array with str_split():

Array
(
    [0] => 1
    [1] => 1
    [2] => 0
    [3] => 0
    [4] => 0
    [5] => 0
)

But you can see this is backwards - in binary we number the bits from right to left, not left to right. So you need to reverse it, using array_reverse().

Then you have a nice array of Text_ => active (1 or 0) pairs:

Array
(
    [0] => 0
    [1] => 0
    [2] => 0
    [3] => 0
    [4] => 1
    [5] => 1
)

Upvotes: 3

Related Questions