none
Bitwise advice requested RRS feed

  • Question


  •             /*
                 * Environment: Visual Studio 2010 (Dotnet 4.0) (Legacy Project)
                 This code works. Is there a better way to extract the two middle bits?
                 Here are the four possible values for the two middle bits. */
                Byte b00 = Convert.ToByte("11100111", 2);
                Byte b01 = Convert.ToByte("11101111", 2);
                Byte b10 = Convert.ToByte("11110111", 2);
                Byte b11 = Convert.ToByte("11111111", 2);

                /*
                 Shift first three bits off to the left.
                 Then shift everything back 6 bits.
                 There must be a cleaner better way?*/
                Byte zero = (Byte)((Byte)(b00 << 3) >> 6);
                Byte one = (Byte)((Byte)(b01 << 3) >> 6);
                Byte two = (Byte)((Byte)(b10 << 3) >> 6);
                Byte three = (Byte)((Byte)(b11 << 3) >> 6);

                Console.WriteLine(zero); // Prints 0
                Console.WriteLine(one); // Prints 1
                Console.WriteLine(two); // Prints 2
                Console.WriteLine(three);// Prints 3
                
                /*
                 * Thanks for your time.
                 * *
    Wednesday, January 22, 2020 6:35 PM

All replies

  • Use bitwise AND to extract bits you want.

    //Middle bits are 00011000 = 24
    byte middleBits00 = (byte)(b00 & 24);
    byte middleBits01 = (byte)(b01 & 24);
    byte middleBits10 = (byte)(b10 & 24);
    byte middleBits11= (byte)(b11 & 24);

    The returned value will be 1 where there are the corresponding 1 in the original value or 0 otherwise. Hence the results above are 0, 8, 16, 24 corresponding to the bit patterns of the mask.

    If you want the original values back of 0, 1, 2, 3 (which is what happens when you shift) then shift right by 6.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 22, 2020 7:19 PM
    Moderator
  • Thanks for your reply.

    I do need the value of the bits. As they represent a number: 0,1,2,3,  they are just in the wrong place in the original byte. (It's from a mp3 bit-stream header byte.)

    If it's possible to get the value of the 2 bits in one operation, that would be even better.

    I don't need to print out the 4 values one at a time. I just need the value of what the 2-bits represent. The returned value can be Int or byte.

    Thanks.


    Wednesday, January 22, 2020 9:57 PM
  • Right, use the mask and then shift by 3 bits. Something like this I believe.

    //Produces 0-3 depending upon the middle 2 bits
    (byte)((value & 24) >> 3)
    For integral values you can leave off the (byte) cast. This is only needed to convert the final value to a byte like your example.


    Michael Taylor http://www.michaeltaylorp3.net

    Wednesday, January 22, 2020 10:02 PM
    Moderator
  • Thanks again. I think your solution is better than mine. As for performance I am guessing that your solution might use less instructions (god knows what the compiler does with our code). My solution requires a (Byte) cast to work correctly, ugh!

    And now for those following this:

    My question was: How do you extract the two middle bits: 00011000;

    My Solution:

    Int32 three = (Byte)(b11 << 3) >> 6;

    Michaels Solution:

    Int32 three= ((b11 & 24)>>3);

    Can anyone else offer an additional information?

    Thursday, January 23, 2020 7:44 AM
  • Check this variation too:

    byte b = 0b00011000;

    int i = ( b >> 3 ) & 0b11;

     

    You can also obtain (b & 0b11000) and work with these unshifted numbers (0, 8, 16, 24), if you do not need the 0-3 values.

    Thursday, January 23, 2020 9:28 AM
  • Thanks, so another choice is available.

    You solution is using a new C# prefix 0b, i'm using C# 4.0.

    I'm assuming that: & 0b11 is syntactic sugar (or equivalent) for: & 3

    Now that I think about it, that can't be syntactic sugar as it's takes 5 characters & 0b11 instead of two & 3

    Ha! Ha! Ha!

    But for those people who live in the past like me here is I believe the same code using C#2.0 / 4.0:

    Byte b00 = Convert.ToByte("11100111", 2);
                Byte b01 = Convert.ToByte("11101111", 2);
                Byte b10 = Convert.ToByte("11110111", 2);
                Byte b11 = Convert.ToByte("11111111", 2);

                int i = (b00 >> 3) & 3;
                 Console.WriteLine(i);
                 i = (b01 >> 3) & 3;
                 Console.WriteLine(i);
                 i = (b10 >> 3) & 3;
                 Console.WriteLine(i);
                 i = (b11 >> 3) & 3;
                 Console.WriteLine(i);

    Thursday, January 23, 2020 2:22 PM
  • "As for performance I am guessing that your solution might use less instructions "

    Actually the performance should be the same for several reasons. Firstly the JIT will likely optimize the call anyway. Secondly shift and bitwise operators all map to a single assembly instruction that takes 1 cycle. So doing 1 shift or 1 bitwise operator has the same CPU time. But you can verify this if you want.

    Honestly if this is the slowest part of your entire code base then your code doesn't need optimizations. The only reason I'd switch from the double shift is because a mask and shift is more clear to most people then 2 shifts. In other words it is strictly an ease of reading issue to me.


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, January 23, 2020 2:35 PM
    Moderator
  • Yes, bit manipulation should be pretty darn fast. I've been using .Net since it was in beta the late 1990's. There isn't much I can't do generally speaking in C# after 20 plus years of working with it every day.

    That said, I'm pretty bored with C# development and so I started learning embedded systems targeting MicroChips microcontrollers. There are about 3 main Developer Environments for programming MicroChip parts.

    I (and probably most people), take for granted the ridiculous resources that we have as developers on a windows computer. Gigabytes of RAM, Terra bytes of Disk Storage. Opening an MP3 file and putting it into a byte array (memory) is nothing. And while we are doing that there are hundreds if not thousands of threads running on the OS.

    Now I'll compare that developer experience (windows & C#), to development for an 8-bit MicroChip microcontroller:

    Cons:
    The IDE tools (for the big three), are nothing compared to Visual Studio IDE. They are terrible. It's like comparing a horse drawn buggy to a Jet air plane. Visual Studio and C# & C++ CLI have spoiled us all.

    Pros:

    I find the task of programming a micro controller fascinating, because they cost .35 cents and at it's slowest speed runs at around 4Mhz (same as my IBM-XT in 1986). But the fact that it is not running 5000 threads in the background, it's incredibly fast and can do amazing stuff.

    It's like building a wind up alarm clock from scratch, once you build and wind it up it never crashes and then does something when the bell goes off. Amazing!

    Finally, the resources available in those embedded system IDE's are pretty much limited to: Arrays, pointers, and bit shifting. Aaah! The good old days of C and C++ using notepad as an IDE.

    -Thanks

    Thursday, January 23, 2020 4:20 PM
  • Yes, bit manipulation should be pretty darn fast

    [...] to development for an 8-bit MicroChip microcontroller

    Something to note here: In "big" processors, we are used to bit manipulation being pretty fast because the ALU includes a barrel shifter that can shift any number of bits in one clock cycle. This is not necessarily the case for a small inexpensive processor, where bit shifting is done by microcode looping through one bit at a time. This means that shifting bits left or right in such a processor can by significantly slower than bitwise operations. So the assertion done in an earlier response about "... shift and bitwise operators all map to a single assembly instruction that takes 1 cycle" might not be true for such a processor.
    Friday, January 24, 2020 7:24 AM
    Moderator