Converting Integers to Binary in Power Apps

Say what?!

This is the 2nd part of a series that should probably be called “Silly Challenges in Power Apps for Nerds”. You can find the first part here: Converting Binary to Integers in Power Apps.

Once again I will vaguely allude to the fact that there are good reasons to do this and all shall be revealed in the fullness of time. In the meantime, if you need it – here ya go!

When it comes to math, you have many terrible tool options. Thanks for choosing Power Apps!

Let’s do it!

Converting numeric values to their binary equivalent (as text) is a little more challenging than the reverse. This isn’t really because the concept is much harder, it’s more that Power Apps makes us work a little harder. But speaking of concepts, here’s Chris’ 2 minute summary of binary to integer math:

Some Background

The main thing we need to know is that binary digits (1 or 0) indicate if the value they represent are “on” or “off”. In our case, when the digit is “on” (1) then the value it represents will be added with all the other “on” values and this total will be the number we’re looking for.

Something to keep in mind that we didn’t have to directly worry about when we were going from binary to number is the “size” of the numeric data type. This just means the number of digits (bits). The bigger the number, the more bits required. For instance, 255 in binary is 11111111. 8 digits = 8 bits. More on this in a moment.

The Code

Once again, a beautiful screen was created in my Canvas Power App:

We’ve got a textbox called txtToBinary and a label under Result that is set to a variable called binaryResult

Here’s what is in the OnSelect for the button:

If(CountRows(binaryDigits)=0,
ClearCollect(binaryDigits,[]);
ForAll(Sequence(31,30,-1),
Collect(binaryDigits, {
index: Value,
worth: Power(2,Value)
})
)
);
ClearCollect(intToBinary,[]);
With({
firstDigit: CountRows(binaryDigits) – 1, //starting point depending on the number of binary digits
input: Value(txtToBinary.Text)
},
ForAll(binaryDigits,
With({
remainder: If(index = firstDigit, input, Last(intToBinary).remaining) //what's left to process (starts with input and decreases)
},
Collect(intToBinary,{
binary: If(remainder >= worth, "1", "0"), //Actual binary digit (left to right)
remaining: If(remainder >= worth, remainder – worth, remainder) //process what's left
})
)
)
);
Set(binaryResult,
With({
full: Concat(intToBinary,binary)
},
Right(full, Len(full) – Find("1",full) + 1) //trims leading zeros (unnecessary really)
)
);

Let’s look at what’s happening line by line:

  • Line 1 – In order to run through our conversion, we need all the positional values figured out ahead of time (so we can loop through them). This is a quick check to make this all a single chunk of code.
    • Basically, we are saying only initialize this collection if it’s empty (checked using the CountRows function). If you are only doing binary to numbers calculations infrequently then this is fine. More likely, however, you could just remove this condition and put lines 2-8 in your App.OnStart.
  • Line 2Clearing/Initializing our binaryDigits collection
  • Line 3 – We start a ForAll loop against an arbitrary collection we generate with Sequence.
    • As mentioned previously, this combination acts as a backwoods for loop. This is even more obvious here because of the parameters. The first number (31) is the total number of rows we want. The second number (30) is what the first number should be. The final number (-1) is the steps between the row values.
    • We are saying give us a collection of numbers from 30 to 0.
    • You might be surprised to see 31 instead of 32. The reason for this is that normal integers are 32-bits but only 31 of those are bits that represent the numeric value and the other is the sign (+ or -). This allows you to calculate the binary equivalent of numbers up to 2,147,483,647.
  • Line 4 – We store a record in our binaryDigits collection for every time we loop through our temporary collection from Sequence
  • Line 5 – The index value is set to the number we get from Sequence. Later we’ll use this value to determine if we’re on the first digit or not (this allows us to change the “size” of our temporary collection without having to update our conversion code).
  • Line 6 – We store the positional value (worth) as a Power of 2 of the Sequence number. This is because of this handy chart:
  • The resulting collection will look something like this:
This was for an 8-bit number: Sequence(8,7,-1) and only shows the first 5 (of 8) rows
  • Line 11 – We are using a temporary collection (intToBinary) to store results as we process the binaryDigits collections. So, we clear it out before starting.
  • Lines 12-15 – Using a With function we setup a couple of local variables
    • firstDigit is set to the total number of rows in the binaryDigits collection minus one. This allows us to know what the “size” of the number will be without having to hardcode it.
    • input is set to the Text Input’s Value so that we don’t have to reference it directly each time making our code more portable.
  • Line 16 – We start a ForAll loop against every row in our binaryDigits collection we just generated above.
  • Lines 17-19 – We use another With function to setup the remainder. We get this by using the Last function to pull in our most recently added item in the collection (the last iteration of the loop) unless this is the first iteration (index = firstDigit) in which case we use the full value of the input.
  • Lines 20-23 – We are calculating which positional values to add together position by position. This requires us to remember what the value of the input is as it changes (subtracting the “on” values), but there is no way to set results from within a ForAll. Fortunately, you can call Collect within a ForAll so we’re doing exactly that and storing our results and our progress as we go.
  • Line 21 – This is the actual binary digit and we are determining if it should be “on” (1) or “off” (0). We do this by looking to see if the positional value (worth) is greater than or equal to the remaining value. If it is, then we turn it “on” (set it to “1”) otherwise we turn it “off” (set it to “0”).
  • Line 22 – To calculate the additional bits, we need to know what’s left (remaining) of the original input. So if we just stored a 1, we subtract the positional value (worth) and store that for calculating the next digit. If it was a 0, then we just pass the value on unchanged.
  • Line 28 – We’ve been calculating as we went but our values are spread across our temporary collection. So we need to extract that value out and save it. In this case we are setting it to a global variable that is referenced by our result label.
  • Lines 29-31 – We use another With function to make it easier to reference our full binary value. If we just want the raw value then this could be skipped and you could just set the binaryResult to this directly. But, we want to trim all the leading zeros to make it easier to read.
    • We use the Concat function to slap all the binary columns of our temporary collection into a single line of text. This works because we evaluated from left to right meaning our calculated digits are already in order.
  • Line 32 – We use a combination of the Right, Len, and Find functions to calculate where the first “1” is in our result and cut off all the extra zeros before that.

Perhaps looking inside the intToBinary collection will help make sense of what we built:

There you have it! Now you can FINALLY convert numbers to binary strings. Wowee!

Looking for more exciting low level looping in Power Apps? Come back for Part 3: Getting the Binary Value of an ASCII Character in Power Apps!

Converting Binary to Integers in Power Apps

But… why?

I promise there are legitimate reasons why you might have to work with binary integers in Power Apps and that’ll be more obvious near the end of this series which should probably be titled “Doing low level operations in Power Apps for masochists”. For now, know it’s possible and if you need to do it here’s the guide.

Let’s do it!

Converting binary values (as text) to their numeric values is “relatively” straight-forward (at least for this series). There are a bunch of guides on how to convert from base 2 to base 10 conceptually and if you’re interested in all the details, go check em out! For our purposes, here’s a basic overview (don’t weep hardcore computer scientists):

A Brief but Boring Background of Some Binary Stuff

Binary digits (1 or 0) indicate if the value it represents is “on” or “off”. In this case, “on” (1) means that value should be included when calculating the result. The values start with 1 and double each time so that the values are 1, 2, 4, 8, 16… etc. to whatever “size” for the data type (read right to left):

As you can see from the image above, the values (1,2,4,8,16…) are really just increasing powers of 2. We’re going to use that fact to our advantage.

So to convert binary to a number, add the values to each other whenever there’s a 1 in the corresponding positions.

The Actual Expression

I went all out in my Canvas Power Apps design skills and created the following screen:

I’ve got a textbox called txtFromBinary and a label under Result that is set to a variable called intResult

Here’s the contents of the OnSelect for the button:

ClearCollect(binaryToInt,[]);
With({
input: txtFromBinary.Text
},
ForAll(Sequence(Len(input)),
With({
binaryDigit: Right(Left(input,Len(input)-(Value-1)),1) //Grab the right most digit
},
Collect(binaryToInt,{
binaryDigit: binaryDigit, //Not necessary (debug)
value:If(binaryDigit = "1", Power(2,Value-1), 0), //Not necessary (debug)
runningTotal:If(binaryDigit = "1", Power(2,Value-1), 0) + If(Value=1, 0, Last(binaryToInt).runningTotal)
})
)
)
);
Set(intResult,Last(binaryToInt).runningTotal);

Let’s look at what’s happening line by line:

  • Line 1 – We are using a temporary collection (binaryToInt) to store intermediate results as we process the binary text character by character. So, we clear it out before starting.
  • Lines 2-4 – Using the With function we can setup a local variable called input which we can reference rather than the Text Input’s Value each time (and it gets cleaned up at the end)
  • Line 5 – We start a ForAll loop against an arbitrary collection we generate with Sequence.
    • We’re going to see this combination over and over in this series because this is Power Apps’ janky version of a for loop. In this case, we are using it to let us run through a collection that is exactly as long as our binary string (which we get by using the Len function). This makes working with each individual character one at a time possible.
  • Lines 6-8 – Again using the With function (which I absolutely love) we setup a local variable. This time we’re extracting the exact character, binaryDigit, we want to work with.
    • In their infinite wisdom, Power Apps didn’t feel the need to implement a substring function so we’ve got an overly complicated combination of Right and Left to grab a single character. The exact character is determined by the use of the Value keyword which in this case references the number from the Sequence function we used earlier.
  • Line 9 – We are calculating a running total of the final value but there’s no way to set results from within a ForAll. Fortunately, you can call Collect within a ForAll so we’re doing exactly that and storing our calculations as we go.
  • Line 10 – This is just for debugging and isn’t used at all but helps us verify we pulled the right bit
  • Line 11 – Also just for debugging, it helps us identify that we calculated the positional value correctly
  • Line 12 – This is the actual calculation where we are adding 2 numbers together.
    • The first is the positional value for a bit which is 0 when the bit is “off” (0) and calculated as a Power of 2 when “on” (1). We use the Value keyword which references the number from the Sequence function used earlier. However, we have to subtract one because Sequence starts with 1 (rather than 0).
    • The second number is the running total we’ve been calculating on the previous bits. We get this by using the Last function to pull in our most recently added item in the collection (the last iteration of the loop) unless this is the first iteration (Value=1) in which case it’s just 0.
  • Line 17 – Since we were calculating as we went, we know that the very last value of our temporary collection is the final result. So we grab it and set it to a global variable to be referenced in our label.

Looking in our temporary collection, binaryToInt might make it a little easier to understand:

Or maybe it didn’t?! Oh well!

The good news is that it works – so copy and paste as you please. And for those of you who can’t get enough of doing things in Power Apps that were not intended to be done in Power Apps, be sure to come back for Part 2: Converting Integers to Binary in Power Apps!