Link to home
Start Free TrialLog in
Avatar of charlieb01
charlieb01

asked on

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

Hello,
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?

Thanks,
Charlie
ASKER CERTIFIED SOLUTION
Avatar of Ess Kay
Ess Kay
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of charlieb01
charlieb01

ASKER

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?

Thanks
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
    Console.WriteLine(valve)
Next

Open in new window

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
        Next
        Console.WriteLine("Done")
    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)
        Debug.Print("==========================")
        For i = 1 To 20
            Debug.Print(String.Format("valve #{0} selected: {1}", i, IsValveSelected(i, x)))
        Next

Open in new window

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
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)

So:
mask starts: 1 or (00000000000001)

Open in new window

AND with Value
00010001011101 
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
00010001011101 
00000000000010 AND
00000000000000 Result is 0 - therefore valve 2 is NOT set

Open in new window


SHIFT and AND
00010001011101 
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
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