I have a set of five boolean values. If more than one of these are true I want to excecute a particular function. What is the most elegant way you can think of that would allow me to check this condition in a single if() statement? Target language is C# but I'm interested in solutions in other languages as well (as long as we're not talking about specific built-in functions).
One interesting option is to store the booleans in a byte, do a right shift and compare with the original byte. Something like if(myByte && (myByte >> 1)) But this would require converting the separate booleans to a byte (via a bitArray?) and that seems a bit (pun intended) clumsy... [edit]Sorry, that should have been if(myByte & (myByte - 1)) [/edit]
Note: This is of course very close to the classical "population count", "sideways addition" or "Hamming weight" programming problem - but not quite the same. I don't need to know how many of the bits are set, only if it is more than one. My hope is that there is a much simpler way to accomplish this.
I was going to write the Linq version, but five or so people beat me to it. But I really like the params approach to avoid having to manually new up an array. So I think the best hybrid is, based on rp's answer with the body replace with the obvious Linqness:
public static int Truth(params bool[] booleans)
{
return booleans.Count(b => b);
}
Beautifully clear to read, and to use:
if (Truth(m, n, o, p, q) > 2)
How about
if ((bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) +
(bool4? 1:0) + (bool5? 1:0) > 1)
// do something
or a generalized method would be...
public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
{
int trueCnt = 0;
foreach(bool b in bools)
if (b && (++trueCnt > threshold))
return true;
return false;
}
or using LINQ as suggested by other answers:
public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
{ return bools.Count(b => b) > threshold; }
EDIT (to add Joel Coehoorn suggestion:
(in .Net 2.x and later)
public void ExceedsThreshold<T>(int threshold,
Action<T> action, T parameter,
IEnumerable<bool> bools)
{ if (ExceedsThreshold(threshold, bools)) action(parameter); }
or in .Net 3.5 and later:
public void ExceedsThreshold(int threshold,
Action action, IEnumerable<bool> bools)
{ if (ExceedsThreshold(threshold, bools)) action(); }
or as an extension to IEnumerable<bool>
public static class IEnumerableExtensions
{
public static bool ExceedsThreshold<T>
(this IEnumerable<bool> bools, int threshold)
{ return bools.Count(b => b) > threshold; }
}
usage would then be:
var bools = new [] {true, true, false, false, false, false, true};
if (bools.ExceedsThreshold(3))
// code to execute ...
It's time for the obligatory LINQ answer, which in this case is actually quite neat.
var bools = new[] { true, true, false, false, false };
return bools.Count(b => b == true) > 1;
I would just cast them to ints and sum.
Unless you're in a super tight inner loop, that has the benefit of being easy to understand.
if you mean more than or equal to one boolean equals to true, you could do it like
if (bool1 || bool2 || bool3 || bool4 || bool5)
If you need more than one (2 and above) booleans equal to true, you can try
int counter = 0;
if (bool1) counter++;
if (bool2) counter++;
if (bool3) counter++;
if (bool4) counter++;
if (bool5) counter++;
if (counter >= 2) //More than 1 boolean is true
I'd write a function to receive any number of boolean values. It would return the number of those values that are true. Check the result for the number of values you need to be positive to do something.
Work harder to make it clear, not clever!
private int CountTrues( params bool[] booleans )
{
int result = 0;
foreach ( bool b in booleans )
{
if ( b ) result++;
}
return result;
}
If there were millions instead of just 5 you could avoid Count()and do this instead ...
public static bool MoreThanOne (IEnumerable<bool> booleans)
{
return booleans.SkipWhile(b => !b).Skip(1).Any(b => b);
}
If your flags are packed into one word then Michael Burr's solution will work. However, the loop is not necessary:
int moreThanOneBitSet( unsigned int v)
{
return (v & (v - 1)) != 0;
}
example
v (binary) | v - 1 | v&(v-1) | result
------------+-------+---------+--------
0000 | 1111 | 0000 | false
0001 | 0000 | 0000 | false
0010 | 0001 | 0000 | false
0011 | 0010 | 0010 | true
.... | .... | .... | ....
1000 | 0111 | 0000 | false
1001 | 1000 | 1000 | true
1010 | 1001 | 1000 | true
1011 | 1010 | 1010 | true
1100 | 1011 | 1000 | true
1101 | 1100 | 1100 | true
1110 | 1101 | 1100 | true
1111 | 1110 | 1110 | true
Shorter and uglier than Vilx-s version:
if (((a||b||c)&&(d||e))||((a||d)&&(b||c||e))||(b&&c)) {}
from the top of my head, a quick approach for this specific example; you could convert the bool to an int (0 or 1). then loop through therm and add them up. if the result >= 2 then you can execute your function.
While I like LINQ, there are some holes in it, like this problem.
Doing a count is fine in general, but can become an issue when the items your counting take a while to calculate/retrieve.
The Any() extension method is fine if you just want to check for any, but if you want to check for at least there's no built in function that will do it and be lazy.
In the end, I wrote a function to return true if there are at least a certain number of items in the list.
public static bool AtLeast<T>(this IEnumerable<T> source, int number)
{
if (source == null)
throw new ArgumentNullException("source");
int count = 0;
using (IEnumerator<T> data = source.GetEnumerator())
while (count < number && data.MoveNext())
{
count++;
}
return count == number;
}
To use:
var query = bools.Where(b => b).AtLeast(2);
This has the benefit of not needing to evaluate all the items before returning a result.
[Plug] My project, NExtension contains AtLeast, AtMost and overrides that allow you to mix in the predicate with the AtLeast/Most check. [/Plug]
Casting to ints and summing should work, but it's a bit ugly and in some languages may not be possible.
How about something like
int count = (bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + (bool4? 1:0) + (bool5? 1:0);
Or if you don't care about space, you could just precompute the truth table and use the bools as indices:
if (morethanone[bool1][bool2][bool3][bool4][bool5]) {
... do something ...
}
I would do something like this, using the params argument.
public void YourFunction()
{
if(AtLeast2AreTrue(b1, b2, b3, b4, b5))
{
// do stuff
}
}
private bool AtLeast2AreTrue(params bool[] values)
{
int trueCount = 0;
for(int index = 0; index < values.Length || trueCount >= 2; index++)
{
if(values[index])
trueCount++;
}
return trueCount > 2;
}
if (NumberOfTrue(new List<bool> { bool1, bool2, bool3, bool4 }) >= 2)
{
// do stuff
}
int NumberOfTrue(IEnumerable<bool> bools)
{
return bools.Count(b => b);
}
Not exactly pretty... but here's another way to do it:
if (
(a && (b || c || d || e)) ||
(b && (c || d || e)) ||
(c && (d || e)) ||
(d && e)
)
I have a much much better one now and very short!
bool[] bools = { b1, b2, b3, b4, b5 };
if (bools.Where(x => x).Count() > 1)
{
//do stuff
}
I wanted to give a C++11 variadic template answer.
template< typename T>
T countBool(T v)
{
return v;
}
template< typename T, typename... Args>
int countBool(T first, Args... args)
{
int boolCount = 0;
if ( first )
boolCount++;
boolCount += countBool( args... );
return boolCount;
}
simply calling it as follows creates a rather elegant method of counting the number of bools.
if ( countBool( bool1, bool2, bool3 ) > 1 )
{
....
}
In most languages true is equivalent to a non-zero value while false is zero. I don't have exact syntax for you, but in pseudo code, what about:
if ((bool1 * 1) + (bool2 * 1) + (bool3 * 1) > 2)
{
//statements here
}
If you only have five different values, you can easily do the test by packing the bits in to a short or an int and checking to see if it is any of the zero or one bit answers. The only invalid numbers you could get would be..
0x 0000 0000
0x 0000 0001
0x 0000 0010
0x 0000 0100
0x 0000 1000
0x 0001 0000
This gives you six values to search for, put them in a lookup table and if it's not in there, you have your answer.
This gives you a simple answer.
public static boolean moreThan1BitSet(int b)
{
final short multiBitLookup[] = {
1, 1, 1, 0, 1, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
if(multiBitLookup[b] == 1)
return false;
return true;
}
This doesn't scale well past 8 bits, but you only have five.
if((b1.CompareTo( false ) + b2.CompareTo( false ) + b3.CompareTo( false ) + ...) > 1)
// More than one of them are true
...
else
...
You mentioned
One interesting option is to store the booleans in a byte,
do a right shift and compare with the original byte.
Something like if (myByte && (myByte >> 1))
I don't think that expression will give you the result you want (at least using C semantics, since the expression is not valid C#):
If (myByte == 0x08), then the expression will return true even though there's only one bit set.
If you meant "if (myByte & (myByte >> 1))" then if (myByte == 0x0a) the expression will return false even though there are 2 bits set.
But here are some techniques for counting the number of bits in a word:
Bit Twiddling Hacks - Counting bits
A variation you might consider is to use Kernighan's counting method, but bail out early since you only need to know if there's more than one bit set:
int moreThanOneBitSet( unsigned int v)
{
unsigned int c; // c accumulates the total bits set in v
for (c = 0; v && (c <= 1); c++)
{
v &= v - 1; // clear the least significant bit set
}
return (c > 1);
}
Of course, using a lookup table's not a bad option either.
performance oriented solutions
As the following statements are true in .NET
sizeof(bool) == 1
*(byte*)&someBool == 1 where someBool is true
*(byte*)&someBool == 0 where someBool is false
you could fall back to unsafe code and pointer casting (as C# will not allow simply casting bool to byte or int).
Your code would then look something like this
if (*(byte*)&bool1 + *(byte*)&bool2 + *(byte*)&bool3 > 1)
{
// do stuff
}
The benefit here would be that you don't have any additional branching making this one faster than the obvious myBool ? 1 : 0.
The drawback here would be the usage of unsafe and pointers which often isn't a well received solution in the managed .NET world. Also the assumption that sizeof(bool) == 1 could be questioned as this doesn't apply to all languages but at least in C# .NET it holds true.
If the pointer stuff is too annoying for you, you could always hide it in an extension method:
using System.Runtime.CompilerServices;
// ...
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe int ToInt(this bool b) => *(byte*)&b;
your code would then turn into a more readable
if (bool1.ToInt() + bool2.ToInt() + bool3.ToInt() > 1)
{
// do stuff
}
Obviously you could always combine this with LINQ as you please
if (myBools.Sum(b => b.ToInt()) > 1)
{
// do stuff
}
or if you value performance over anything else this one's probably faster
bool[] myBools = ...
fixed (bool* boolPtr = myBools)
{
byte* bytePtr = (byte*)boolPtr;
int numberOfTrueBools = 0;
// count all true booleans in the array
for (int i = 0; i < myBools.Length; numberOfTrueBools += bytePtr[i], i++);
// do something with your numberOfTrueBools ...
}
Or if you have a huge input array you could even go for a hardware accelerated SIMD solution ...
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
// ...
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
public static unsafe int CountTrueBytesSIMD(this bool[] myBools)
{
// we need to get a pointer to the bool array to do our magic
fixed (bool* ptr = myBools)
{
// reinterpret all booleans as bytes
byte* bytePtr = (byte*)ptr;
// calculate the number of 32 bit integers that would fit into the array
int dwordLength = myBools.Length >> 2;
// for SIMD, allocate a result vector
Vector128<int> result = Vector128<int>.Zero;
// loop variable
int i = 0;
// it could be that SSSE3 isn't supported...
if (Ssse3.IsSupported)
{
// remember: we're assuming little endian!
// we need this mask to convert the byte vectors to valid int vectors
Vector128<int> cleanupMask = Vector128.Create(0x000000FF);
// iterate over the array processing 16 bytes at once
// TODO: you could even go to 32 byte chunks if AVX-2 is supported...
for (; i < dwordLength - Vector128<int>.Count; i += Vector128<int>.Count)
{
// load 16 bools / bytes from memory
Vector128<byte> v = Sse2.LoadVector128((byte*)((int*)bytePtr + i));
// now count the number of "true" bytes in every 32 bit integers
// 1. shift
Vector128<int> v0 = v.As<byte, int>();
Vector128<int> v1 = Sse2.ShiftRightLogical128BitLane(v, 1).As<byte, int>();
Vector128<int> v2 = Sse2.ShiftRightLogical128BitLane(v, 2).As<byte, int>();
Vector128<int> v3 = Sse2.ShiftRightLogical128BitLane(v, 3).As<byte, int>();
// 2. cleanup invalid bytes
v0 = Sse2.And(v0, cleanupMask);
v1 = Sse2.And(v1, cleanupMask);
v2 = Sse2.And(v2, cleanupMask);
v3 = Sse2.And(v3, cleanupMask);
// 3. add them together. We now have a vector of ints holding the number
// of "true" booleans / 0x01 bytes in their 32 bit memory region
Vector128<int> roundResult = Sse2.Add(Sse2.Add(Sse2.Add(v0, v1), v2), v3);
// 4 now add everything to the result
result = Sse2.Add(result, roundResult);
}
// reduce the result vector to a scalar by horizontally adding log_2(n) times
// where n is the number of words in out vector
result = Ssse3.HorizontalAdd(result, result);
result = Ssse3.HorizontalAdd(result, result);
}
int totalNumberOfTrueBools = result.ToScalar();
// now add all remaining booleans together
// (if the input array wasn't a multiple of 16 bytes or SSSE3 wasn't supported)
i <<= 2;
for (; i < myBools.Length; totalNumberOfTrueBools += bytePtr[i], i++);
return totalNumberOfTrueBools;
}
}
I was recently having this same issue, where I had three boolean values, which I needed to check that only 1 of them was true at a time. For this I used the xor operator as follows:
bool a = true;
bool b = true;
bool c = false;
if (a || b || c)
{
if (a ^ b ^ c){
//Throw Error
}
}
This code will throw an error as a and b are both true.
For reference: http://www.dotnetperls.com/xor
I have only just found the xor operator in C# if anyone knows of any pit falls of this strategy, please let me know.
Related
I don't know why I am getting wrong bits when reading my byte. I have followed some indications found here, bit it is not working. I show you my code:
byte[] byte22And23 = _packet.ReadBytes(2);
DataFromGTAPackets.Packet8.ControlFlags.rightEngineSmoke = _packet.GetBit(byte22And23[0], 0);
DataFromGTAPackets.Packet8.ControlFlags.leftEngineSmoke = _packet.GetBit(byte22And23[0], 1);
DataFromGTAPackets.Packet8.ControlFlags.rightEngineFire = _packet.GetBit(byte22And23[0], 2);
DataFromGTAPackets.Packet8.ControlFlags.leftEngineFire = _packet.GetBit(byte22And23[0], 3);
DataFromGTAPackets.Packet8.ControlFlags.rightRotorFail = _packet.GetBit(byte22And23[0], 4);
DataFromGTAPackets.Packet8.ControlFlags.leftRotorFail = _packet.GetBit(byte22And23[0], 5);
etc...
public bool GetBit(byte b, int bitNumber)
{
bool bit = (b & (1 << bitNumber - 1)) != 0;
return bit;
}
My byte 22 has a value of 2, it is: 00000010. And my byte 23 has a value of 0. When I use this code to read byte 22, my 3rd variable (rightEngineFire) is getting "true" (1). It has no sense, it is wrong obviously. But I don't know what is wrong.
Thank you!
You GetBit method considers bit numbers to be 1...32, instead of being 0...31.
Simple test:
bool b1 = GetBit(1, 0); // false
bool b2 = GetBit(1, 1); // true
You should change the method to
public static bool GetBit(byte b, int bitNumber)
{
bool bit = (b & (1 << bitNumber)) != 0;
return bit;
}
Or you could write:
DataFromGTAPackets.Packet8.ControlFlags.rightEngineSmoke = _packet.GetBit(byte22And23[0], 1);
But in C-derived languages (and C# is a C-derived language) we count from 0, so the first solution is better (for me).
And as a sidenote:
1 << bitNumber - 1
is quite unreadable, because probably 9 out of 10 programmers don't know/don't remember that the expression means
1 << (bitNumber - 1)
because in the operator precedence table the - comes before the <<, so when you mix operators you should use (...) to make clear the priority.
The GetBit() implementation is wrong, you can check with the following test:
[TestMethod]
public void MyTestMethod()
{
var byte22And23 = new byte[] { 2, 0 };
var sb = new StringBuilder();
for (int i = 7; i >=0; i--)
{
var r = GetBit(byte22And23[0], i);
sb.Append((r) ? "1" : "0");
}
// result: 00000100
Assert.AreEqual("00000010", sb.ToString());
}
It looks like there is no need of -1 in GetBit() because you are indexing bits 0-based and not 1-based:
public bool GetBit(byte b, int bitNumber)
{
// no need of -1 here ------------ˇ
bool bit = (b & (1 << bitNumber - 1)) != 0;
return bit;
}
After the modification the tests runs green.
I have flags
int A = 1;
int B = 2;
int C = 4;
I want to make a check, that only one flag can be specified to a function
check(A | B | C) ; // invalid
check(A); // valid
check(B); // valid
check(B | C); // invalid
void check(int flags) {
// check that if A is specified, then B and C can't
// check that if B is specified, then A and C can't
// check that if C is specified, then B and A can't
}
How can I achieve this without tons of "if" statements?
To set the bit at position n, you want to set value 2^n.
So if you want to check that only one of the flags is specified, then you just want to ask if the number is a power of two.
And here is a question about how to do that: How to check if a number is a power of 2
As GrahamS says, you could read the question as saying that exactly one bit must be set (i.e. it can't be zero). So to do that, in addition, check that it's non-zero and that it's less than or equal to C.
Perhaps not the most elegant solution, but I think it should work:
bool check(int flags) {
int A = 1;
int B = 2;
int C = 4;
return
flags == 0 ||
flags == A ||
flags == B ||
flags == C;
}
Why not use use an Enum for your flags, and check if the int value is defined in the enum.
enum Flags
{
A = 1,
B = 2,
C = 4
}
void Check(int flags)
{
bool isValid = Enum.IsDefined(typeof(Flags), flags);
...
}
Here's an implementation with switch:
void check(int flags) {
swicth (flags & (A | B | C)) {
case A:
case B:
case C:
case 0:
return true;
default:
return false;
}
}
It will work (in C#) only if A, B and C are literals, i.e. marked with const. Otherwise you can do the same with:
void check(int flags) {
int relevantPart = flags & (A | B | C);
return relevantPart == A || relevantPart == B || relevantPart == C || relevantPart == 0;
}
Otherwise use the power-of-two trick (from answer by Joe):
void check(int flags) {
int relevantPart = flags & (A | B | C);
return (relevantPart & (relevantPart - 1)) == 0;
}
I assumed there could be more significant bits than the three least bits, and they were to be ignored. I also assumed that neither A, B, nor C was valid (this is not co-existing in my interpretation).
I was going to comment but what GrahamS said was important enough to warrant some elaboration of the point.
Flags are generally used when you specifically want to be able to set multiples. Here is an example of a our task enum
namespace Shared.Enumerations
{
[Flags]
public enum TaskStatusEnum
{
NotSet = 0,
Open = 1,
Canceled = 2,
Complete = 4,
OnHold = 8,
Inactive = 32,
All = Open | Canceled | Complete | OnHold | Inactive
}
}
We do this so we can say give us any task that is open or on hold.
TaskList activeTasks = taskListManager.TaskList.FindAll(target.Name, target.TaskType, (TaskStatusEnum.Open | TaskStatusEnum.OnHold));
Of course with a normal enumeration you can only set one thing at a time. You could actually do something like the following.
[TestMethod]
public void checkEnumVals()
{
var ts = TaskStatusTestEnum.Open;
ts |= TaskStatusTestEnum.OnHold;
bool matchBoth = false;
if ((ts & TaskStatusTestEnum.OnHold) == TaskStatusTestEnum.OnHold && (ts & TaskStatusTestEnum.Open) == TaskStatusTestEnum.Open)
matchBoth = true;
Assert.IsTrue(matchBoth);
}
I wouldn't suggest something like this though.
I have two bytes, they only differ in 1 bit. I want to know what bit this is.
So:
byte a,b;
a=0;
b=2;
ChangedBit(a,b) should give bit 1
ChangedBit(4,5) should give bit 0
ChangedBit(7,3) should give bit 2
Any suggestions are very welcome!!
Thanks,
Erik
The correct solution would be to do
var bit = Math.Log(a ^ b, 2);
Although of course this leaves open the question of what happens if for any reason more than one bit is different.
You could use
var bit = (int)Math.Log(a ^ b, 2);
to get you the index of the highest different bit, if more than one differ.
Warning: For correctness, any such function should also check that the two arguments a and b are actually different before trying to provide a result. Otherwise you 'll get either a meaningless result or an outright exception. This is true of all the solutions presented here, including this one.
If they differ by one bit, xor should give you just that bit. So then you could shift to find which?
Perhaps needs some optimisation:
static int ChangedBit(int x, int y)
{
uint bits = (uint)(x ^ y); // need uint to avoid backfill with shift
int count = -1;
while (bits != 0)
{
count++;
bits >>= 1;
}
return count;
}
You can do this quite easily:
Math.Log(Math.Abs(a-b), 2)
Update: fixed...
If you can count from zero, then Math.Log(a^b,2) does the job
var dif = a ^ b;
int bitNumber = 0;
while (dif != 0 && ((dif & 1) == 0)
{
dif = dif >> 1;
++bitNumber;
}
// bitNumber now contains the zero relative bit that is different.
Couldn't resist to write a LINQish version:
var firstBits = new BitArray(new byte[] { 3 });
var secondBits = new BitArray(new byte[] { 17 });
var lhs = firstBits.Cast<bool>().Select((b, i) => new { Bit = b, Index = i });
var rhs = secondBits.Cast<bool>().Select((b, i) => new { Bit = b, Index = i });
var differs = lhs.Zip(rhs, (l, r) => new { Left = l, Right = r })
.Where(zipped => zipped.Left.Bit != zipped.Right.Bit)
.Select(zipped => new { Index = zipped.Left.Index, LeftBit = zipped.Left.Bit, RightBit = zipped.Right.Bit });
foreach (var diff in differs)
{
Console.WriteLine(String.Format("Differs in bit {0}:", diff.Index));
Console.WriteLine(String.Format(" First is set to {0}", diff.LeftBit));
Console.WriteLine(String.Format(" Second is set to {0}", diff.RightBit));
}
Update
Due to the fact that the Zip operator is not a default in LINQ, you can get the implementation from Eric out of his blog.
Others have observed that where two bytes differ in only one bit, an XOR operation will return a byte in which just that bit is set. But no one has yet suggested what to me is the obvious next step for establishing which bit that is:
public static int WhichBitDiffers(byte a, byte b)
{
var xor = a ^ b;
switch(xor)
{
case 0x80:
return 7;
case 0x40:
return 6;
case 0x20:
return 5;
case 0x10:
return 4;
case 0x8:
return 3;
case 0x4:
return 2;
case 0x2:
return 1;
case 0x1:
return 0;
default:
throw new ArgumentException(
"Values do not differ in exactly one bit");
}
}
I bet the compiler / JITter will make this a nice compact jump lookup table, or something along those lines.
I have a value thats 5 bits in length. 4 bits determine the number and the 5th bit determines the sign, there by holding any value between -16 and +15. How can I accomplish sign extending from a constant bit width in C#? I know in C, I can use something like the follow to accomplish this:
int x; // convert this from using 5 bits to a full int
int r; // resulting sign extended number goes here
struct {signed int x:5;} s;
r = s.x = x;
How can I do something similar to this in C#?
It's not really clear what you mean, but it could be as simple as:
int fiveBits = normal & 0x1f;
and for the reverse:
int normal = fiveBits < 16 ? fiveBits : fiveBits | -32;
If you could suggest some original input and desired output, that would help.
Perform a left shift followed by an arithmetic right shift to move the sign bit into the high position and then back. The arithmetic right shift will perform the sign extension for you.
Of course this depends on having a working arithmetic shift operation. The abstract C language does not (it's implementation-defined whether it works or not), but most implementations do. I'm not sure about C# but I would guess it has one.
I know this is an old question, but for future searchers I have more info.
C# does not support custom bit widths, but it does support binary operations and getters/setters, which makes it relatively easy to add a compatibility layer. For instance, if you want to store the raw data in a byte _num, but want to be able to interact with it using a standard C# sbyte, you can use the following:
byte _num;
sbyte num {
get
{
return (sbyte)(((_num & 0x10) << 3) | (_num & 0x0F));
}
set
{
_num = (byte)((value & 0x0F) | ((value & 0x80) >> 3));
}
}
This kind of shell is especially useful when interacting with low level firmware or embedded projects.
I'm just writing a C function (because I don't really know C#) that will do this using operations that I know are available in C#.
int five_bit_to_signed(int five_bit) {
int sh = (sizeof(int)*8)-5;
int x = five_bit << sh; // puts your sign bit in the highest bit.
return x >> sh; // since x is signed this is an arithmatic signed shift
}
From your question, it appears you wish to have a structure that can readily be converted to and from an int type:
struct FiveBit
{
public int bits;
public static implicit operator int(FiveBit f)
{
return (f.bits & 0x10) == 0 ? f.bits : f.bits | -32;
}
public static implicit operator FiveBit(int r)
{
return new FiveBit() { bits = r & 0x1f };
}
}
And here's an example of usage:
class FiveBitTest
{
static void Main(string[] args)
{
FiveBit f = new FiveBit();
int r; // resulting sign extended number goes here
f.bits = 0;
r = f;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
f.bits = 0x1f;
r = f;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
r = -2;
f = r;
Console.WriteLine("r = {0}, f.bits = 0x{1:X}", r, f.bits);
}
The output of the above is:
r = 0, f.bits = 0x0
r = -1, f.bits = 0x1F
r = -2, f.bits = 0x1E
Is there a way to convert an int to a bitmask?
example:
int i = 33;
should be converted to (not sure of the datatype)
bool[] bitmask = new[] {true, false, false, false, false, true};
Update
In reaction to most answers:
I need to do this:
BitArray bits = new BitArray(BitConverter.GetBytes(showGroup.Value));
List<String> showStrings = new List<string>();
for (int i = 0; i < bits.Length; i++)
{
if(bits[i])
showStrings.Add((i+1).ToString().PadLeft(2, '0'));
}
How would that go without converting it to a bitarray?
An int already is a bitmask. If you want to twiddle the bits, you can use bitwise operators freely on ints. If you want to convert the int to an enum that has the Flags attribute, a simple cast will suffice.
Found it
BitArray bits = new BitArray(System.BitConverter.GetBytes(showGroup.Value));
You could construct a bool[32] and loop through all bits in the int, masking it with 2^(loop counter) and setting the bools in the array appropriately.
Are you sure you need this, though? Most operations with bitmasks work with ints directly.
To answer the question in your edit:
int val = 35;
List<string> showStrings = new List<string>();
for (int i = 0; i < 32; i++)
{
if (( (1 << i) & val) > 0)
{
showStrings.Add((i + 1).ToString().PadLeft(2, '0'));
}
}
prints:
01
02
06
Not the most obvious solution if you're not used to bit arithmetic, true. Mask each bit in the integer value with 2^(bit-index), and if the resulting value is greater than zero (indicating that the bit at that index is set), do something. 1 << i (left-shifting) is equivalent to 2^i, and may have the same performance characteristics once JITted, but I'm used to this form.
Expressed as a macro-like method:
bool IsSet(int val, int index)
{
return (( (1 << (index-1)) & val) > 0);
}
int val = 33;
var bitarray = new BitArray(new[] { val });
var att = bitarray.Cast<bool>().ToArray();
Since you asked, here is a solution without using BitArray:
// First define a bitmask enum for the bits you are interested in
[Flags]
public enum BitFlags
{
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 8,
Flag5 = 16
// ...
}
int index = 0;
List<string> showStrings = new List<string>();
foreach(int flag in Enum.GetValues(typeof(BitFlags))cast<int>())
{
index += 1;
if ((input & flag) == flag)
showStrings.Add(index.ToString().PadLeft(2, '0'));
}
It is about the same amount of code, with negligible performance difference. It does however let you strongly define your bit values and you can choose to omit bits in the BitFlags enum that you don't care about.