Using an integer to store multiple values in C#

Suppose that you are creating a game in which your character obtains some awards out of some predefined one, as the game goes by. Or, you’re creating software in which you want your user to select some entries/items (imagine something like a checked list box). In both cases, you could try and use these two approaches

  1. Create or use a data structure (e.g. Dictionary<K,V>) in which you store a reference to all possible items along with the relevant Boolean value. Easy right? In order to answer the question if user has obtained item X, you just check the value of the relevant key in the dictionary.
  2. Create or use a data structure (e.g. List<T>) in which you store references to the items the user has obtained/picked. So, you can use the List.Contains method to check for an item’s existence.

Both described methods are efficient, easy to grasp and use. However, there is another method in which you do not need to use nothing more advanced than a simple integer. We’ll be using binary system arithmetic and logic to accomplish this purpose.

Each number can be written in binary format in a sequence of 1s and 0s. For instance, 15 is binary 1111 and 2 is binary 0010. Most importantly, all numbers that are a power of two start with 1 and finish with some 0s. Check the below list

Binary – Base 10

So, if you assign e.g. “valueA”to 1, “valueB” to 2, “valueC” to 4 etc., you can easily assign multiple values into an integer. How? You just add the relevant base 10 value to this integer, let’s call it storage. For instance, the integer 13 contains 3 values: a)1, b)4, c)8. In binary form, it is written as 1101. The way to check for a value’s existence is a logical bitwise AND between the storage and the respective value. In C#, we use the & for this purpose. If the result of the operation is equal to the value, then storage contains this value. Simple, right? Check the below C# code for the value 19.

int storage = 19; //10011
int a = 1; //1
int b = 2; //10
int c = 4; //100
int d = 8;//1000
int e = 16;//10000
Console.WriteLine("Check for the value 19 - 10011");
Console.WriteLine($"Does {storage} contain \"a\" with the value of 1? " + ((storage & a) == a)); //true
Console.WriteLine($"Does {storage} contain \"b\" with the value of 2? " + ((storage & b) == b)); //true
Console.WriteLine($"Does {storage} contain \"c\" with the value of 4? " + ((storage & c) == c)); //false
Console.WriteLine($"Does {storage} contain \"d\" with the value of 6? " + ((storage & d) == d)); //false
Console.WriteLine($"Does {storage} contain \"e\" with the value of 8? " + ((storage & e) == e)); //true

Another way to understand/remember it is that each digit in the number’s binary form is something like a flag. For example, if you count digits starting from the last one (and begin counting from zero) and the 4th position has the value 1, then the number contains the value 2^3 (=8).

The only drawback using this method is that you cannot use it for more than 32 items (for a System.Int32 .NET type, since its maximum value is 2^32 – 1). So, how about a more concrete example? Let’s suppose that we want to check if a user has selected some cities. First, we need to create a 1:1 relationship between each city and a number, which will of course be a power of two.

Dictionary<string,int> dict = new Dictionary<string,int> ();
 dict.Add("Athens", (int)Math.Pow(2, 0)); //1
 dict.Add("Thessaloniki", (int)Math.Pow(2, 1)); //2
 dict.Add("Kozani", (int)Math.Pow(2, 2)); //4
 dict.Add("Larisa", (int)Math.Pow(2, 3)); //8
 dict.Add("Komotini", (int)Math.Pow(2, 4)); //16
 dict.Add("Trikala", (int)Math.Pow(2, 5)); //32
 dict.Add("Patra", (int)Math.Pow(2, 6)); //64

Then, we’ll let the user pick some cities, which will be added to an integer. A simple addition and we’re done.

int myStorage = dict["Athens"] + dict["Komotini"] + dict["Larisa"];

Let’s check some cities manually.

//does it contain Komotini?
 Console.WriteLine("Does it contain Komotini? " + ((myStorage & dict["Komotini"]) == dict["Komotini"])); //true

//does it contain Larisa?
 Console.WriteLine("Does it contain Larisa? " + ((myStorage & dict["Larisa"]) == dict["Larisa"])); //true

//does it contain Patra?
 Console.WriteLine("Does it contain Patra? " + ((myStorage & dict["Patra"]) == dict["Patra"])); //false

And a check on every city

foreach (var item in dict)
 if ((myStorage & item.Value) != 0) //check every city
 Console.WriteLine("It does contain {item.Key}");
 Console.WriteLine("It does not contain {item.Key}");

If you need to remove a value, just subtract it from the storage.

Console.WriteLine("Let's remove Larisa");
 //remove Larisa
 myStorage = myStorage - dict["Larisa"];
 //does it contain Larisa?
 Console.WriteLine("Now, does it contain Larisa? " + ((myStorage & dict["Larisa"]) == dict["Larisa"]));

I’ve used this trick into an app I’ve co-developed, called Math Puppy. In this app, the child gets awarded with various accessories for his/her dog as the game progresses. I wanted something simple to store the awarded stuff, so I used this method. Nice and easy!

Update (7/1/2016): As my friend Nikolaos Georgiou pointed out to me on Twitter, you can use Enum with [Flags] attribute if you have a few values that are known in compile time. This wouldn’t work, however, if the values are dynamic e.g. from a database.

The entire sample source code is listed below. Happy coding!

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s