-1

I need to read 8 bool values and create a Byte from it, How is this done? rather than hardcoding the following 1's and 0's - how can i create that binary value from a series of Boolean values in c#?

byte myValue = 0b001_0000;
Faust
  • 97
  • 1
  • 1
  • 4
  • A byte is just a "tiny int" that you still can use in calculations. And bits have specific values (1,2,4,8,...,128) – Hans Kesting Jul 09 '21 at 14:24
  • Like [this](https://stackoverflow.com/questions/11204666/converting-c-sharp-byte-to-bitarray)? – Andy Jul 09 '21 at 14:25
  • 1
    Check out BitArray https://learn.microsoft.com/en-us/dotnet/api/system.collections.bitarray?view=net-5.0 – Greg Jul 09 '21 at 14:31

4 Answers4

3

There's many ways of doing it, for example to build it from an array:

bool[] values = ...;
byte result = 0;
for(int i = values.Length - 1; i >= 0; --i)  // assuming you store them "in reverse"
    result = result | (values[i] << (values.Length - 1 - i));
Blindy
  • 65,249
  • 10
  • 91
  • 131
1

My solution with Linq:

public static byte CreateByte(bool[] bits)
        {
            if (bits.Length > 8)
            {
                throw new ArgumentOutOfRangeException();
            }
            return (byte)bits.Reverse().Select((val, i) => Convert.ToByte(val) << i).Sum();
        }

The call to Reverse() is optional and dependent on if you want index 0 to be the LSB (without Reverse) or the MSB (with Reverse)

Rypox
  • 533
  • 3
  • 8
1
        var values = new bool[8];
        values [7] = true;            
        byte result = 0;
        for (var i = 0; i < 8; i++)
        {
           //edited to bit shifting because of community complains :D
           if (values [i]) result |= (byte)(1 << i);
        }
        // result => 128
lidqy
  • 1,891
  • 1
  • 9
  • 11
0

This might be absolutely overkill, but I felt like playing around with SIMD. It could've probably been written even better but I don't know SIMD all that well.

If you want reverse bit order to what this generates, just remove the shuffling part from the SIMD approach and change (7 - i) to just i

For those not familiar with SIMD, this approach is about 3 times faster than a normal for loop.

public static byte ByteFrom8Bools(ReadOnlySpan<bool> bools)
{
    if (bools.Length < 8)
        Throw();
            
    static void Throw() // Throwing in a separate method helps JIT produce better code, or so I've heard
    {
        throw new ArgumentException("Not enough booleans provided");
    }

    // these are JIT compile time constants, only one of the branches will be compiled
    // depending on the CPU running this code, eliminating the branch entirely
    if(Sse2.IsSupported && Ssse3.IsSupported)
    {
        // copy out the 64 bits all at once
        ref readonly bool b = ref bools[0];
        ref bool refBool = ref Unsafe.AsRef(b);
        ulong ulongBools = Unsafe.As<bool, ulong>(ref refBool);

        // load our 64 bits into a vector register
        Vector128<byte> vector = Vector128.CreateScalarUnsafe(ulongBools).AsByte();

        // this is just to propagate the 1 set bit in true bools to the most significant bit
        Vector128<byte> allTrue = Vector128.Create((byte)1);
        Vector128<byte> compared = Sse2.CompareEqual(vector, allTrue);

        // reverse the bytes we care about, leave the rest in their place
        Vector128<byte> shuffleMask = Vector128.Create((byte)7, 6, 5, 4, 3, 2, 1, 0, 8, 9, 10, 11, 12, 13, 14, 15);
        Vector128<byte> shuffled = Ssse3.Shuffle(compared, shuffleMask);

        // move the most significant bit of each byte into a bit of int
        int mask = Sse2.MoveMask(shuffled);

        // returning byte = returning the least significant byte from int
        return (byte)mask;
    }
    else
    {
        // fall back to a more generic algorithm if there aren't the correct instructions on the CPU
        byte bits = 0;
        for (int i = 0; i < 8; i++)
        {
            bool b = bools[i];
            bits |= (byte)(Unsafe.As<bool, byte>(ref b) << (7 - i));
        }
        return bits;
    }
}
Petrusion
  • 940
  • 4
  • 11