C# and flags/bit tests - "Except if" - ... how to? - c#

Messy title, but am feeling the veins in my brain snap in vain while trying to find a "pretty" (=readable & easily maintainable) way to figure out a way to do something like this in simple terms:
[Flags]
enum SomeFlags {
_unset_ = 0,
SomeFlag = 1 << 1,
ExceptionalFlag = 1 << 16,
}
private SomeFlags someenum = SomeFlags._unset_;
...
int times = 1;
while(times > 0)
{
times--;
...
rnd_num = /*make random number in range X to Y*/ fooRandom();
...
if (rnd_num <= arbitrary_const &&
( !someenum.HasFlag(Flags.SomeFlag)
[[except if]]
somenum.HasFlag(Flags.ExceptionalFlag) )
)
{
/* do stuff if numeric condition matches, AND someenum does
-not- contain SomeFlag, EXCEPT if someenum has -also-
ExceptionalFlag set alongside SomeFlag */
}
else if (...yaddayadda...)
...
else {
times++;
someenum |= SomeFlags.ExceptionalFlag;
continue;
}
break;
}
Maybe?:
if ( /* some_numeric_condition == */ true &&
(!someenum.HasFlag(Flags.SomeFlag) ||
someenum.HasFlag(Flags.SomeFlag | Flags.ExceptionalFlag) ) )
{ /* foobar */ }
Is there any "simpler" way to express such?
Just clearing my mind, as that sort of test's buried behind/in pretty lots of code and I'm not familiar with 'unit testing' stuff yet.
Truth table which is sought for:
SomeFlag SomeFlag|ExceptionalFlag True?
0 0 true
1 0 false
0 1 false
1 1 true
edit: clarifying a little (I hope) - the if stuff is within a loop, in this particular case... and conditions change.
edit2: edited for truth table sought... And mucked that up, so - another #3 go!

If you're looking for a shorter equivalent to the code you already have, since that does seem to match your description, you could try
!(someenum.HasFlag(Flags.SomeFlag) && !someenum.HasFlag(Flags.ExceptionalFlag))
It comes across as
unless SomeFlag is set and ExceptionalFlag is not set
as opposed to your original
if SomeFlag is not set, or both flags are set
It's not really much shorter or clearer, it's just a different way of looking at it.

Your snippet:
(!someenum.HasFlag(Flags.SomeFlag)
|| someenum.HasFlag(Flags.SomeFlag | Flags.ExceptionalFlag) )
Turns out to be exactly equivelant to:
!someenum.HasFlag(Flags.SomeFlag) || someenum.HasFlag(Flags.ExceptionalFlag)
There's no need to specify that SomeFlag is set - as we've already proved it's not if we enter the second check.
Here's the truth table:
SomeFlag ExceptionalFlag Expected Result
0 0 1
0 1 1
1 0 0
1 1 1

Related

How to loop through check boxes and assign enumeration values when boxes are checked?

I have a group of check boxes, to be precise there are 3 boxes. It works for me when using if statement but I wonder there is a way to loop through check boxes and assign enumeration values when a box is checked or more.
The code looks like this:
if (chkTomato.Checked && !chkLettuce.Checked && !chkCarrot.Checked)
{
cart.VegChosen = Veggies.Tomato;
}
else if (!chkTomato.Checked && chkLecctuce.Checked && !chkCarrot.Checked)
{
cart.VegChosen = Veggies.Lecctuce;
}
else if (!chkTomato.Checked && !chkLecctuce.Checked && chkCarrot.Checked)
{
cart.VegChosen = Veggies.Carrot;
}
else if (chkTomato.Checked && chkLettuce.Checked && chkCarrot.Checked)
{
cart.VegChosen = Veggies.All;
}
else if (chkTomato.Checked && chkLettuce.Checked && !chkCarrot.Checked)
{
cart.VegChosen = Veggies.TomatoAndLettuce;
}
else if (chkTomato.Checked && !chkLettuce.Checked && chkCarrot.Checked)
{
cart.VegChosen = Veggies.TomatoAndCarrot;
}
else if (!chkTomato.Checked && chkLettuce.Checked && chkCarrot.Checked)
{
cart.VegChosen = Veggies.LettuceAndCarrot;
}
else
{
cart.VegChosen = Veggies.None;
}
I want to find out a way to loop it in case there are more than just 3 check boxes, the if statement would be very long.
Thank you!
While this doesn't use loops, I expect this is what you're trying to achieve. Assuming your enum is declared like this:
[Flags]
public enum Veggies
{
None = 0,
Tomato = 1,
Lettuce = 2,
Carrot = 4,
TomatoAndLettuce = Tomato | Lettuce,
TomatoAndCarrot = Tomato | Carrot,
LettuceAndCarrot = Lettuce | Carrot,
All = Tomato | Lettuce | Carrot
}
Then you should be able to use a similar bitwise approach to assign values:
Veggies selectedVeggies = Veggies.None;
if (chkTomato.Checked)
{
selectedVeggies = selectedVeggies | Veggies.Tomato;
}
if (chkLettuce.Checked)
{
selectedVeggies = selectedVeggies | Veggies.Lettuce;
}
if (chkCarrot.Checked)
{
selectedVeggies = selectedVeggies | Veggies.Carrot;
}
cart.VegChosen = selectedVeggies;
The net result of this will be the same as your current set of if statements. The reason we use 1, 2, 4, etc. for the enum values is because there isn't overlap between them when rendered in binary (1 is 001, 2 is 010, 4 is 100, etc.) so that specific bit can only identify that one enum value.
Also note that declarations such as TomatoAndLettuce and TomatoAndCarrot are perhaps also unnecessary, since you can use Enum.HasFlag().
For example:
var selectedVeggies = Veggies.Tomato | Veggies.Carrot;
// or var selectedVeggies = Veggies.TomatoAndCarrot; // effectively the same as above
if (selectedVeggies.HasFlag(Veggies.Tomato))
{
cart.Add(new Tomato());
}
if (selectedVeggies.HasFlag(Veggies.Carrot))
{
cart.Add(new Carrot());
}
// cart ends up with a Tomato and a Carrot
Further reading: What does the bitwise or | operator do?
Create the enum like so:
enum Veggies {
Tomato = 1 << 0,
Lettuce = 1 << 1,
Carrot = 1 << 2,
All = Tomato | Lettuce | Carrot
}
This makes the value of Veggies.Tomato = 1 which is 0000 0001 in bits, Veggies.Lettuce = 2 which is 0000 0010, and Veggies.Carrot = 4 which is 0000 0100.
It is important to have the enum values as bit-shifted 1's (powers of 2) so that you can combine two enum values later as an int like I've done with Veggies.All, which is 0000 0111.
Change VegChosen to an int, then simply change your code to something like this to bitwise-or the enum value into the VegChosen int:
cart.VegChosen = 0;
if(chkTomato.Checked) cart.VegChosen |= Veggies.Tomato;
if(chkLettuce.Checked) cart.VegChosen |= Veggies.Lettuce;
if(chkCarrot.Checked) cart.VegChosen |= Veggies.Carrot;
Later if you want to test what veggies were chosen from cart.VegChosen you can bitwise-and with one of the enum values and check if it's 0 like so:
if((cart.VegChosen & Veggies.Carrot) != 0)
{
//... cart.VegChosen contains Veggies.Carrot
}
if((cart.VegChosen & Veggies.Lettuce) != 0)
{
//... cart.VegChosen contains Veggies.Carrot
}
//etc
This is typically ~50% faster/more performant than Enum.HasFlag() because HasFlag() contains various sanity checks, but if you're not programming specifically for performance it's better to use what is easier to use and read and in that respect I would recommend Llama's answer.
Once you e implemented Llamas answer of making a flags enum you can put all your checkboxes in a groupbox and do this:
var veg = Veggies.None:
groupbox.Controls
.OfType<CheckBox>()
.Where(c => c.Checked)
.ToList()
.ForEach(c => veg |= Enum.Parse<Veggies>(c.Name[3..]));
Then all you have to do is add more enum members and add more checkboxes where the checkbox name is like "chkXXX" where xxx is the name of the enum member
This is a looping construct: it gets all the controls on the groupbox and filters to only those of type checkbox, then reduces it to only checked checkboxes. It turns this into a list (so we can foreach it, because foreach is a list thing not a LINQ thing). Foreach will visit every checkbox and ask if it is checked, it will OR the existing flags enum value with the result of parsing the checkbox name (dropping the first 3 chars) to a Veggies. At the end of it your veg variable will represent all the checkboxes that were Checked
Note that using ranges and even Enum.Parse<T> required a fairly modern version of c# - if you're running a version that doesn't support ranges you can use Substring(3). You should make sure that all your checkbox names are well aligned with your enum names. If you want to get really trick you could create your checkboxes dynamically by enumerating the Enum and putting the enum value as the checkbox Tag when you add the control to the form (dynamically, in incrementing positions) this way your form will just adapt automatically to however many enum members you have

Protecting against Divide by Zero

I'm running into a problem that I think in my mind should work, but keep returning the same Divide by Zero error.
Here is the code I am using that I think should protect against it:
GoalBarValue = Convert.ToInt32(((decimal)CompletedToday /
((decimal)CompletedYesterday) == 0 ? (decimal?)null : (decimal)CompletedYesterday)
* 100); // Divide by zero protection
CompletedToday comes back as 0
CompletedYesterday comes back as 0
Which is perfectly fine and as I expect it should.
The specific error that is being returned is Attempted to divide by zero.
Is something wrong with the way I am trying to protect against it?
"Is something wrong with the way I am trying to protect against it?"
Yes actually, you are dividing by zero! The only way that 0 can be the outcome of your calculation is when CompletedToday is 0. In the other case you divide by 0 and get the nice exception. Why don't you just check whether the divisor is 0 and if not perform the calculation else give it a null :
GoalBarValue = Convert.ToInt32((decimal)CompletedYesterday) == 0 ?
(decimal?)null : (decimal)CompletedYesterday * 100;
Imagine you would check whether you hit your head against a wall by hitting your head against the wall..... it wouldn't be advisable.
EDIT:
If you want 2 assignments of different variables (as you wrote in your comment) then the ? operator is not of much use to you. It allows only 1.
I would suggest to stick to the old fashion way. If you really want the 2 assignments in one line:
if((decimal)CompletedYesterday) == 0)
GoalBarValue = CompletedYesterday = null;
else GoalBarValue = // what ever you want to calculate...
Is this what you want?
if (Convert.ToDecimal(CompletedYesterday) == 0)
{
goalBarValue = null;
}
else
{
goalBarValue = Convert.ToInt32(Convert.ToDecimal(CompletedToday)/Convert.ToDecimal(CompletedYesterday)) * 100;
}
one line version of above code
goalBarValue = Convert.ToDecimal(CompletedYesterday) == 0 ? null : Convert.ToInt32(Convert.ToDecimal(CompletedToday)/Convert.ToDecimal(CompletedYesterday)) * 100;

Non-boolean "truth table" creation

I have the following problem: I need to create a table, which is combination of values coming from sets. The cardinality of the elements in the set is unknown, and may vary from set to set, the domain of the values is unknown, and may as well vary from set to set. The elements in the set are non-negative, at least two elements are within a set.
Here follows an example:
SET_A = { 0, 1, 2 }
SET_B = { 0, 1 }
SET_C = { 0, 1 }
The result should contain the following rows (order is not a constraint):
TABLE:
| 0 0 0 |
| 0 0 1 |
| 0 1 0 |
| 0 1 1 |
| 1 0 0 |
| 1 0 1 |
| 1 1 0 |
| 1 1 1 |
| 2 0 0 |
| 2 0 1 |
| 2 1 0 |
| 2 1 1 |
Does anybody know which is the Mathematics behind this problem? I tried to look at Multiset problems, logic tables, combinatorics. Many of the definitions that I found have similarities to my problem, but I can't isolate anything in the literature that I have accessed so far. Once I have a reference definition I can think of coding it, but now I just got lost in recursive functions and terrible array-index games. Thanks.
EDIT: Question was proposed already at:
C# Permutation of an array of arraylists?
Edit: Sorry, had to run last evening. For arbitrary dimensionality you probably would have to use recursion. There's probably a way to do without it, but with recursion is most straightforward. The below is untested but should be about right.
IEnumerable<int[]> getRows(int[][] possibleColumnValues, int[] rowPrefix) {
if(possibleColumnValues.Any()) { //can't return early when using yield
var remainingColumns = possibleColumnValues.Skip(1).ToArray();
foreach(var val in possibleColumnValues.First()) {
var rowSoFar = rowPrefix.Concat(new[]{val}).ToArray();
yield return getRows(remainingColumns rowSoFar);
}
}
}
Usage:
getRows(new [][] {
new [] {0,1,2},
new [] {0,1},
new [] {0,1},
}, new int[0]);
The thing you look for is combinatorics. Also it doesn't really matter what is the domain of the elements in set. As long as you can enumerate them, the problem is the same as for numbers from 0 to the set cardinality.
To enumerate all options, have a vector of indices and after each iteration increment the first index. If it overflows, set to 0 and increment the second index, etc.
The task is to print permutations. You seem to dig deeper then it is. It has nothing to do with nature of elements.
The following is not written for efficiency (neither in space nor speed). The idea is to just get the basic algorithm across. I'll leave making this more space and time efficient up to you.
The basic idea is to recognize that all the combinations of n lists, is just all the combinations of n-1 lists with each element of the first list tacked on. It's a pretty straight-forward recursive function at that point.
public static IEnumerable<int[]> Permute( params IEnumerable<int>[] sets )
{
if( sets.Length == 0 ) yield break;
if( sets.Length == 1 )
{
foreach( var element in sets[0] ) yield return new[] { element };
yield break;
}
var first = sets.First();
var rest = Permute( sets.Skip( 1 ).ToArray() );
var elements = first.ToArray();
foreach( var permutation in rest )
{
foreach( var element in elements )
{
var result = new int[permutation.Length + 1];
result[0] = element;
Array.Copy( permutation, 0, result, 1, permutation.Length );
yield return result;
}
}
}

Beginner c# trouble

Im new to c# and Im having a little problem. I want to make an easy program to ask the user for a integer number between 1-50, and then to display on the console if its a odd number or not. So, what i tried is this:
Console.WriteLine("Skriv ut ett heltal: ");
int x = int.Parse(Console.ReadLine());
if (x == 1,3,5,7,9,11,13,15,17,19)
{
Console.WriteLine("The number is odd");
}
else
{
Console.WriteLine("The number is not odd");
}
Now i get an error at my if statements condition. How can i fix this?
C# does not allow you specify multiple values to check a variable against using a single if statement. You would need to check each value (1, 3, 5, etc) individually if you wanted to do it this way, and that would be a lot of redundant typing.
In this particular example, an easier way to check if something is odd or even is to check the remainder after dividing by 2, using the modulus operator %:
if (x % 2 == 1)
{
Console.WriteLine("The number is odd");
}
else
{
Console.WriteLine("The number is even");
}
However, if you really do need to check against a list, then the easy way is to use the Contains method on an array (an ICollection<T>, really). To make it nice and easy, you could even write an extension function that lets you check against a list in a syntactically pretty fashion:
public static class ExtensionFunctions
{
public static bool In<T>(this T v, params T[] vals)
{
return vals.Contains(v);
}
}
Then you could say:
if (x.In(1,3,5,7,9,11,13,15,17,19))
{
Console.WriteLine("The number is definitely odd and in range 1..19");
}
else
{
Console.WriteLine("The number is even, or is not in the range 1..19");
}
Voila! :)
if(x % 2 == 0)
{
// It's even
}
else
{
// It's odd
}
If you want to test whether x is a number in a particular list:
int[] list = new int[]{ 1,3,5,7,9,11,13,15,17,19};
if(list.Contains(x))
The common way to check to see if an integer is odd is to check if it divides evenly by 2:
if(x % 2 == 1)
x == 1,3,5,7,9,11,13,15,17,19 is not valid syntax for expressing multiple options. If you really want to do this then you can use a switch statement:
switch(x) {
case 1:
case 3:
case 5:
case 7:
case 9:
case 11:
case 13:
case 15:
case 17:
case 19:
// is odd
break;
default:
// is even
break;
}
The correct way would be to use the modulo operator % to determine if a number is exactly divisible by 2 or not, rather than trying every odd number, like so:
if( x % 2 == 0 ) {
// even number
} else {
// odd number
}
That's not valid C#. You can't test set inclusion like that. In any case, it's not practical to test for all the numbers in the world.
Why don't you just do this instead;
if (x &1 == 1) // mask the 1 bit
Bitwise operations are pretty quick so that code should be pretty fast.
Your if statement should be like this if you are having multiple conditions:
if any 1 of conditions is true:
if(x == 1 || x == 3 || x == 5)
{
//it is true
}
if all of the condition must be true:
if(x == 1 && y == 3 && z == 5)
{
//it is true
}
But if you are only looking for odd/even numbers. Use the % operator as the other answer says.
While, as others have pointed out, this is not the best way to solve this problem, the reason you're getting an error in this case is because you can't have multiple values like that in an if statement. You have to word it like this:
if (x == 1 || x == 3 || x == 5)
If you don't know, || is the symbol for 'or'
Try the following:
Console.WriteLine("Skriv ut ett heltal: ");
int x = int.Parse(Console.ReadLine());
Console.WriteLine(x % 2 == 1 ? "The number is odd" : "The number is not odd");
x % 2 == 1 does a modulus of 2 on the input (takes as many '2's off as possible until the number is between 0 and 2 - so 0 or 1 in this case)
One way to do that is:
if (x == 1 || 3 || 5){
Console.writeLine("oddetall");
}
or so it is possible to create an Array []
int[] odd = new int[3]; // how many odd to be tested
if(x=odd){
Console.WriteLine("Oddetall");
}

Simple interval/range intersection with overflow

I'm writing a physical memory manager that gets some intervals of memory from the BIOS that are not used by crucial system data. Each interval has 0 <= start <= 2^32 - 1 and 0 <= length <= 2^32. I have already filtered out the zero-length intervals.
Given two intervals S and T, I want to detect how they intersect. For example, does S start before T and end within T (picture a)? Or does S start before T and end after T (picture c)?
You'd think the solution is trivial:
uint s_end = s_start + s_length;
uint t_end = t_start + t_length;
if (s_start < t_start)
// S starts before T
else if (s_start < t_end)
// S starts within T
else
// S starts after T
if (s_end <= t_start)
// S ends before T
else if (s_end <= t_end)
// S ends within T
else
// S ends after T
The problem is overflow: I am technically limited to a 32-bit integer and the intervals can (and often do) use the whole range of available integers. For example in figure b, t_end equals 0 due to overflow. Or even, as in figure f t_start = t_end = s_start = 0 while t_length != 0.
How can I make these interval intersection conditions work with overflow taken into account?
The overflow screws up my conditions, but I really can't use a 64-bit integer for this (that would be easiest). I know it must be possible using some clever reshuffling of my conditions and using addition and subtraction, but after making endless diagrams and thinking about it for hours, I can't seem to be able to wrap my head around it.
While my problem is with 32-bit integers, in this image I used 4-bit integers just to simplify it. The problem remains the same.
OK, the issue is, if you want your ranges to span all of n-bits, any calculations based on start/end has the potential to overflow.
So the trick is to do a linear transform to a place where your start/end calculations do not overflow, do your calcs, and then linear transform back.
NOTES
Below the we can safely call end() now line, you can call the ordering checks (your original code) and it will be safe since the ordering is preserved during a linear transform.
Also, as I noted in the previous post, there is a special boundary case where even if you do this transform, you will overflow (where you span the entire line) - but you can code for that special boundary condition.
OUTPUT
5 11
CODE
#include <iostream>
using type = uint8_t;
struct segment
{
type start, length;
type end() const { return start + length; }
};
static segment
intersect( segment s, segment t )
{
type shift = std::min( s.start, t.start );
// transform so we can safely call end()
s.start -= shift; // doesn't affect length
t.start -= shift; // doesn't affect length
// we can safely call end() now ----------------------------------------------
type u_start = std::max( s.start, t.start );
type u_end = std::min( s.end(), t.end() );
type u_length = u_end - u_start;
segment u{ u_start, u_length };
// transform back
u.start += shift;
return u;
}
int main()
{
segment s{ 3, 13 }, t{ 5, 11 };
segment u = intersect( s, t );
std::cerr << uint32_t( u.start ) << " " << uint32_t( u.length ) << std::endl;
return 0;
}
Your example code does not enumerate all the cases. For example the intervals could also start or end at the same point.
To solve the overflow problem you could try to add different math based on the start comparison that will not include computing the ends at all. Something like:
if (s_start < t_start)
{
// S starts before T
uint start_offset = t_start - s_start;
if (start_offset < s_length)
{
if (s_length - start_offset < t_length)
{
// ...
}
else ...
} else ...
}
One solution is to treat an end of 0 as a special case. Weaving this into the if-statements, it becomes:
uint s_end = s_start + s_length;
uint t_end = t_start + t_length;
if (s_start < t_start)
// S starts before T
else if (t_end == 0 || s_start < t_end)
// S starts within T
else
// S starts after T
if (s_end != 0 && s_end <= t_start)
// S ends before T
else if (t_end == 0 || s_end == t_end
|| (s_end != 0 && s_end <= t_end))
// S ends within T
else
// S ends after T
This looks correct.
I don't know what do you do with conditions like (f), since 32-bit t_length will be 0 there.
Assuming you've managed this case somehow when you were filtering out length=0, which can mean both 0 and 2^32, the basic idea is this:
bool s_overflows=false;
if(s_start>0)//can't have overflow with s_start==0,
{
uint32 s_max_length=_UI32_MAX-s_start+1;
if(s_length==s_max_length) s_overflow=true;
}
bool t_overflows=false;
if(t_start>0)
{
uint32 t_max_length=_UI32_MAX-t_start+1;
if(t_length==t_max_length) t_overflow=true;
}
Then you just do your calculations, but if s_overflow is true, you don't calculate s_end -- you don't need it, since you already know it's 0x100000000. The same for t_overflow. Since these are already special cases, just like start=0, they shouldn't complicate your code much.

Categories

Resources