Using BitWise Operator

DikongPrigm 61 Reputation points
2021-09-22T10:24:41.663+00:00

I've come across a code where it uses bitwise operator. I dont understand it well enough. What im trying to do is to save a truck size id but when reading the values, the ID im getting is different.

CODE FOR SAVING

        public int getmergedfields()
        {
            int merged = (int)PriorityLevel;
            merged |= ((int)PriceSource << 4);
            merged |= (((int)BinWeight) << 8);
            // merged |= (((int)WhenToInvoice) << 10);

            // these two flags store whether this job has extended comments for
            // either the comments or the officenotes field
            if (comments.Length > 200)
                merged += 1024; // set the 11th bit
            if (officenotes.Length > 200)
                merged += 2048; // set the 12th bit 
            if (TLPricedPerCube)
                merged += 4096;
            if (SentToMobileDevice)
                merged += 8192;
            // before this property was here things were always saved as ExGST so make that the default
            if (TLPricedIncGST)
                merged += 16384;
            if (DespatchDocketSent)
                merged += 32768;
            if (IsCurrentJob)
                merged += 65536;
            merged += ((int)TruckSize) << 17;    
            return merged;
        }

CODE FOR READING

                int unmerge = JobReader.GetInt32(startat);
                PriorityLevel = (ePriorityLevel) (unmerge & 15); // 0x1111); // priority stored in 4 low bits
                PriceSource = (ePriceSource)((unmerge >> 4) & 15);
                BinWeight = (eBinWeight) ((unmerge >> 8) & 3);
                // whentoinvoice = (eWhenToInvoice)((unmerge >> 10) & 3);
                if ((unmerge & 1024) > 0)
                    extendedcomments = true;
                if ((unmerge & 2048) > 0)
                    extendedofficenotes = true;
                if ((unmerge & 4096) > 0)
                    TLPricedPerCube = true;
                if ((unmerge & 8192) > 0)
                    senttomobiledevice = true;
                if ((unmerge & 16384) > 0)
                    TLPricedIncGST = true;
                if ((unmerge & 32768) > 0)
                    DespatchDocketSent = true;
                if ((unmerge & 65536) > 0)
                    IsCurrentJob = true;
                TruckSize = ((unmerge & ((1 << 17) | (1 << 18))) >> 17);

If the truck size Id is less than or equal to three, it works just fine but when the ID is greater than three, the result im expecting is different.

Honestly, I dont know what this code means.

TruckSize = ((unmerge & ((1 << 17) | (1 << 18))) >> 17);


merged += ((int)TruckSize) << 17;    

I don't know where does the 17 and 18 come from.

C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,288 questions
0 comments No comments
{count} votes

Accepted answer
  1. P a u l 10,406 Reputation points
    2021-09-22T11:27:36.44+00:00

    1 << 17 means take one bit and move it 17 places to the left, so this:

    000000000000000001

    Is coverted into this:

    100000000000000000 (131072 in decimal)

    (1 << 17) | (1 << 18) takes the value above and "bitwise or"'s it with:

    1000000000000000000 (contains extra zero than the number above)

    And that gives us:

    1100000000000000000

    You could also do (3 << 17) here instead of (1 << 17) | (1 << 18) and it'll give you the same result.

    Next the result above is "bitwise and"'ed to unmerge, which will effectively get it's 17th and 18th bits.

    Lastly, the result of that are then shifted right 17 places which will give you the answer in the range of 0 to 3.

    For the purpose of your question my question is: how many bits are reserved in your merged variable for the ID? Currently it only uses 2 bits, so if you wanted to represent higher numbers you'll need to consider that when shifting your bits.


1 additional answer

Sort by: Most helpful
  1. P a u l 10,406 Reputation points
    2021-09-22T13:35:40.56+00:00

    Well to represent the number 20 you'd need to use a minimum of 5 bits (giving you an ID range of 0 to 31.)

    So you'd need to make sure that you have 5 (ideally consecutive) bits available to store the value. Do you have any bits that aren't already in use by other data?

    If you only have 2 bits free and they're the 2 that you're currently using you might want to consider changing the data type of that column to support more bits, although this will be wasteful so it's worth trying to free up any unused bits that you currently have first.