Because the length of the bool array
is uncertain, how can I change it?
bool[] bools=new bool[]{true,true,true,false,true,false,..as.};
short[] shorts= BitConverter.ToInt16(?,0);
I tried the following methods
Each true
is a bit
bool[] bools=new bool[]{true,true,true,false,true,false};
List<bool> list=new List<bool>();
list.AddRange(bools);
int ints= bools.Length%16;
for(int i=0;i<16-ints;i ){
list.Add(false);
}
BitArray bits=new BitArray(list.ToArray());
byte[] bytes= ToByteArray(bits);
short[] shorts=new short[bytes.Length/2];
for(int i=0;i<bytes.Length/2;i )
shorts[i]= BitConverter.ToInt16(bytes);
CodePudding user response:
You can always do it by hand by shifting bits:
bool[] bools = new bool[]
{
true, true, true, false, true, false, true, false,
true, true, true, false, true, true, true, false,
true, false, false, false, false, false, false, false,
true, true, true, true,
};
var shorts = new List<short>();
for (int i = 0; i < bools.Length; i = 16)
{
int current = 0;
for (int j = 0; j < 16; j )
{
current = (current << 1);
if (i j < bools.Length && bools[i j])
{
current = (current | 1);
}
}
shorts.Add((short)current);
}
Console.WriteLine(Convert.ToString(shorts[0], 2));
Console.WriteLine(Convert.ToString(shorts[1], 2));
Should output:
"1110101011101110"
"1000000011110000"
Another alternative would be to convert the bools to strings with 0/1, and use Convert.ToInt16, i.e. Convert.ToInt16("1110101011101011", 2)
I would note that this would be a rather odd thing to do since representing binary data as bools is rather inefficient. It is much more common to represent binary data as byte arrays.
CodePudding user response:
If the first bool value in the array is the left-most bit, try something like this:
bool[] bools = new bool[] { true, true, true, false, true, false, false };
List<short> shorts = new List<short>();
for (int i = 0; i < bools.Length; i )
{
short s = 0;
if (bools[i] == true)
s |= (short)(1 << i % 16);
shorts.Add(s);
}
If the first bool value in the array is the right-most bit, reverse the bool array first before the loop.
bool[] bools = new bool[] { true, true, true, false, true, false, false };
Array.Reverse(bools);
List<short> shorts = new List<short>();
for (int i = 0; i < bools.Length; i )
{
short s = 0;
if (bools[i] == true)
s |= (short)(1 << i % 16);
shorts.Add(s);
}
I didn't test the code, but this should work.
CodePudding user response:
It depends on how would you treat these boolean values. If you have at most 16
bools(true
for 1
, false for 0
),
you can put something like:
using System.Linq;
...
short x = unchecked((short)bools.Aggregate(0, (s, a) => s * 2 (a ? 1 : 0)));
if bools
is of arbitraty length (and you have an array of short
)
short[] shorts = bools
.Select((b, index) => new {b, index})
.GroupBy(pair => pair.index / 16, pair => pair.b ? 1 : 0)
.Select(group => unchecked((short)group.Aggregate((s, a) => s * 2 a)))
.ToArray();
If you want to stick to BitConverter
logic you have to work with byte[]
:
short[] shorts = bools
.Select((b, index) => new {b, index})
.GroupBy(pair => pair.index / 8, pair => pair.b ? 1 : 0)
.Select(group => (byte)group.Aggregate((s, a) => s * 2 a))
.Select((b, index) => new {b, index})
.GroupBy(pair => pair.index / 2, pair => pair.b)
.Select(group => group.ToArray())
.Select(array => array.Length == 2
? BitConverter.ToInt16(array)
: BitConverter.ToInt16(array.Concat(new byte[1]).ToArray()))
.ToArray();
CodePudding user response:
I am a bit confused as to why you are going for 16 bits of chunks while wanting to use a float/ Single, anyway presuming you actually are going for 16 bit values, you could come about to what you ask like the suggestion below.
Please feel free to clarify the usage of Singles as it relates to data and point out what i missed :)
[Fact]
public void ContinuousWordsTest()
{
var rnd = new Random((int)DateTime.Now.Ticks);
var length = rnd.Next(32, 4000);
var boolsList = new List<bool>(length);
for(int i = 0; i < length; i )
{
boolsList.Add(Convert.ToBoolean(rnd.Next(0, 2)));
}
int idx = 0;
var multipliers = new ushort[] { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768};
var resultsList = new List<Single>(); // is in .net same as float
ushort buildNumber = 0;
foreach(var boolish in boolsList)
{
if(boolish)
buildNumber |= multipliers[idx];
idx ;
if (idx % 16 == 0)
{
idx = 0;
resultsList.Add(Convert.ToSingle(buildNumber));
buildNumber = 0;
}
}
Assert.NotEmpty(resultsList);
//TODO: Consider if we don't actually want to use an integral numeric type: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types
//TODO: Consider why using a float at all, if you have 2 bytes and why else be going for 16 bit lumps, hence you really cannot get such big a number anyway
}-