VB. Net Need help decoding a number 2 to the nth power

I have an application where a piece of hardware is going to give my VB.Net program a number to tell me which valves are open. Each valve has a value associated based on 2 to the nth power. So:
Valve01 = 1
Valve02 = 2
Valve03 = 4
Valve04 = 8
Valve05 = 16
etc. (up to 20 Valves)

So, if valves 1, 4 and 5 are open, the number I will get will be 1 + 8 + 16 = 25

I am looking for some help in decoding this so I know which valves are open. For five valves, it is not too difficult as the largest number is 31 but the code would get lengthy when I am looking at 20 valves as the value for the 20th valve alone is 2^19 = 524288.

Dose anyone have a simple way to decode this in VB.net?

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ess KayEntrapenuerCommented:

in c#

int myInteger; // Store integer value here.
string myBinaryString = Convert.ToString(myInteger, 2); // Convert integer to binary string.
BitArray myBitArray = new BitArray(myBinaryString.Length); // Initialise bit array.

// Store True for every "1" and False for every "0".
for(int i = 0; i < myBitArray.Length; i++)
    myBitArray[i] = (myBinaryString.Chars[i] == '1')

Open in new window

in VB

DIM i = 8
Console.WriteLine(Convert.ToString(i, 2).PadLeft(20, "0"C))

Open in new window

the padding 20 will create preceding zeros (up to 20 of them if all valves are closed)

the string has 20 integers 0 or 1

the values are 20 down to 1 left to right

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
charlieb01Author Commented:
I am not a C# programmer but the code looks like it would work except I can't seem to convert it to vb.net
The VB sample does not seem to do anything.

Can you assist in converting your C# into VB?

Fernando SotoRetiredCommented:
Hi charlieb01;

Here is VB code that uses Enums which will give you the valves selected from an integer value.

' Place this at class level outside of any function or subroutine.
<Flags> Private Enum valvesEnum As Integer
       valve01 = 1
       valve02 = 2
       valve03 = 4
       valve04 = 8
       valve05 = 16
       valve06 = 32
       valve07 = 64
       valve08 = 128
       valve09 = 256
       valve10 = 512
       valve11 = 1024
       valve12 = 2048
       valve13 = 4096
       valve14 = 8192
       valve15 = 16394
       valve16 = 32768
       valve17 = 65536
       valve18 = 131072
       valve19 = 262144
       valve20 = 524288
End Enum

' Then in a function, subroutine or event handleryou can do this.
' Test data that the hardware sends to you
Dim valvesSelected As valvesEnum = 25
' Array holds the valves which are open
Dim valves() As String = String.Format("{0:G}", valvesSelected).Split(New Char() {","c, " "c}, StringSplitOptions.RemoveEmptyEntries)

' Output valves that are open
For Each valve In valves

Open in new window

C++ 11 Fundamentals

This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Julian HansenCommented:
The right way to do this is with the binary SHIFT and AND operators
    Sub Main()
        Dim val As Int32
        Dim i As Int32
        Dim valve As Int32

        val = 25 ' The value you receive
        valve = 1 ' Bit mask to check for on values
        ' You can change this for as many valves as your system has
        For i = 0 To 32

            ' AND the value with the current mask to see if the valve is on
            ' and output it if it is

            If val And valve Then
                Console.WriteLine("Valve " & valve & " is open")
            End If

            ' Shift the mask 1 position left for the next match
            valve = valve << 1
    End Sub

Open in new window

  Function IsValveSelected(ByVal index As Integer, ByVal value As Integer) As Boolean
        Return CBool(value And 2 ^ (index - 1))
    End Function

Open in new window

      Dim x As Integer = 25
        Debug.Print("Initial value: " & x)
        For i = 1 To 20
            Debug.Print(String.Format("valve #{0} selected: {1}", i, IsValveSelected(i, x)))

Open in new window

Ess KayEntrapenuerCommented:
the vb code prints out the list of valves like this 00000000000000000001000
left to right

meaning the fourth valve is open

You will see it in the console.

if you want to be sure, send it to a message box like this

dim i = 8
msgbox(Convert.ToString(i, 2).PadLeft(20, "0"C))

DIM i - creates a variable where you add a number, for testing, and we set it to 8, but you can set it to whatever number you need
try 262144 for valve 19
or 262145 for valve 19 and valve 1
Julian HansenCommented:
There should be no need to make use of strings or split functions for this. This type of system has been around for years and is ideally suited to using BITWISE operators to determine what flags are set.

A typical input might be 00010001011101

Indicating that valves 1,3,4,5,7,11 are open

To decode this is a simple exercise using a mask. A mask is a value applied to another value using a bitwise operation (AND / OR / XOR ) to give a new value.

AND is the intersection
OR is the union
XOR is the complement

So to find the valve values start with a mask value of 1.

Loop through the maximum number of flags supported (example 32) and each iteration AND the mask with the value and then shift the mask left 1 position (effectively multiply by 2)

mask starts: 1 or (00000000000001)

Open in new window

AND with Value
00000000000001 AND
00000000000001 Result is > 0 therefore valve 1 is set

Open in new window

Now shift the mask 1 bit to the left
mask = mask << 1

Open in new window

AND again
00000000000010 AND
00000000000000 Result is 0 - therefore valve 2 is NOT set

Open in new window

00000000000100 AND
00000000000100 Result is > 0 therefore valve 3 is set

Open in new window

This above is the simplest and most efficient way of solving this problem. Refer here for source
Ess KayEntrapenuerCommented:
sorry, forgot to mention, but it should of been picked up, the VB i wrote prints to the console.

I gave the code for a mesagebox, or you can do whatever with it, like send it to a variable
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.