BumbleBee
BumbleBee

Reputation: 10799

Get the sum of powers of 2 for a given number + c#

I have a table with different codes. And their Id's are powers of 2. (20, 21, 22, 23...). Based on different conditions my application will assign a value to the "Status" variable. for ex :

Status = 272 ( which is 28+ 24)
Status = 21 ( Which is 24+ 22+20)

If Status = 21 then my method (C#) should tell me that 21 is sum of 16 + 4 + 1.

Upvotes: 8

Views: 7048

Answers (5)

Sumudu Fernando
Sumudu Fernando

Reputation: 1763

You can use bitwise operators for this (assuming that you have few enough codes that the values stay in an integer variable).

a & (a - 1) gives you back a after unsetting the last set bit. You can use that to get the value of the corresponding flag, like:

while (QStatus) {
  uint nxtStatus = QStatus & (QStatus - 1);

  processFlag(QStatus ^ nxtStatus);

  QStatus = nxtStatus;
  }

processFlag will be called with the set values in increasing order (e.g. 1, 4, 16 if QStatus is originally 21).

Upvotes: 2

Armen Tsirunyan
Armen Tsirunyan

Reputation: 133072

for (uint currentPow = 1; currentPow != 0; currentPow <<= 1)
{
   if ((currentPow & QStatus) != 0)
      Console.WriteLine(currentPow); //or save or print some other way
}

for QStatus == 21 it will give

1 
4
16

Explanation: A power of 2 has exactly one 1 in its binary representation. We take that one to be the rightmost one(least significant) and iteratively push it leftwards(towards more significant) until the number overflows and becomes 0. Each time we check that currentPow & QStatus is not 0.

Upvotes: 16

foxy
foxy

Reputation: 7672

This is basically binary (because binary is also base 2). You can bitshift values around !

uint i = 87;

uint mask;
for (short j = 0; j < sizeof(uint); j++)
{
    mask = 1 << j;
    if (i & mask == 1)
        // 2^j is a factor
}

Upvotes: 3

dtb
dtb

Reputation: 217351

You can test all bits in the input value if they are checked:

int value = 21;

for (int i = 0; i < 32; i++)
{
    int mask = 1 << i;
    if ((value & mask) != 0)
    {
        Console.WriteLine(mask);
    }
}

Output:

1
4
16

Upvotes: 18

Anders Abel
Anders Abel

Reputation: 69270

This can probably be done much cleaner with an enum with the [Flags] attribute set.

Upvotes: 5

Related Questions