 # Thread: Decimal Conversion

1. ## Decimal Conversion

Good Morning,

I have been all researching a method in converting a 10 digit decimal number from a rfid card ex: 0002256109
which converts to hex: 226CED I am needing the last four bits (4H) which would be 27885 (226""6CED"") to dump back in as decimal.

The whole reason this is needed is that the rfid software is only accepting 6 digits to provide as access for the user and the card reader is reading the first 10. the only set of numbers on a rfid card that is going to be totally unique is the last 5. ex: 0002256109 034 ""27885""

So I figured there has to be a way to build something in .net that will take the input from the card reader (which is just an emulated keyboard driver anyway) convert to hex and take the last 5 and send that to the program via the keyboard so it would need to run in the background. I may be explaining this in a confusing way but this is what makes sense to me. Let me know if there would be an easier way. Thank you in advance   Reply With Quote

2. ## Re: Decimal Conversion

Sure, it's just a few transformation steps. You need to tell the program to:

• Receive a String that represents a 10-digit number in base 10.
• Convert that base 10 number to base 16.
• Consider only the last 4 digits of the number.
• Convert those 4 base 16 digits to base 10.

So at the top level, you want:
Code:
`Function Convert(ByVal input As String) As ???`
I'm not sure if you want the final result to be a String or a Long, but either one is easy.

How do we get there? One step at a time. Someone might have a clever way to do it on one line, but more clever people like to take it step-by-step so they can verify work in the debugger.

First, we need to read a String that represents a 10-digit number in such a way that we can convert it to another base. This is where a ton of people get really tripped up: if we can represent the number as a Long, the base DOES NOT MATTER. A Long is a number, and we can choose to display it in any base. It is hard to parse a String that represents a base-something number and convert it directly to another String. But if you parse the String to a Long, then format the Long to a String, you accomplish the same goal in two easy steps. Long.Parse() has an argument that lets you specify the input base, and Long.ToString() takes format specifiers that can let you convert to other bases. So I'd write my first step:
Code:
```Function ConvertDecimalToHex(ByVal input As String) As String
Dim parsed As Long = Long.Parse(input)
Return parsed.ToString("X")
End Function```
The default base for numbers is 10, so Long.Parse() doesn't need to be told to do anything special. The "X" format specifier tells .ToString() you want the number to be represented in Hexadecimal.
Code:
```Function GetLast4Digits(ByVal input As String) As String
Dim index As Integer = input.Length - 4
Return input.Substring(index)
End Function```
With the 4 digits in hand, we want to get back to a number. Again, that's a parse then a potential format:
Code:
```Function ConvertHexToDecimal(ByVal input As String) As String
Dim parsed As Long = Convert.ToInt64(input, 16)
Return parsed.ToString()
End Function```
For some reason Parse() doesn't have an overload for a base, so we have to employ the Convert class to parse Strings that represent numbers in hexadecimal.
Code:
```Function ConvertId(ByVal input As String) As String
Dim asHexadecimal As String = ConvertDecimalToHex(input)
Dim trimmed As String = GetLast4Digits(asHexadecimal)
Dim result As String = ConvertHexToDecimal(trimmed)
Return result
End Function```
I think, if I felt so inclined, I could use bitwise operations to skip some steps. For example, "the last 4 hexadecimal digits" actually means "the last two bytes" of a number. So we COULD take advantage of that. What we do is:
Code:
```Function ConvertId(ByVal input As String) As String
Dim parsed As Long = Long.Parse(input)
Dim lastBytes As Long = parsed And &HFFFF
Dim result As Long = lastBytes.ToString()

Return result.ToString()
End Function```
I wish I'd tried that first!  Reply With Quote

3. ## Re: Decimal Conversion

Well, the first question is: What are you actually getting from the reader?

After all, 0002256109 isn't actually a decimal, it's a string. If it were a decimal, you'd just see 2256109. If you are getting a string, then that's a different problem. If you are getting a 10 digit number as a number and not a string, it would have to be a Long, because an Integer couldn't hold that many digits. In any case, if you have either an Integer or a Long, then whether you see that as decimal or hex is up to you, cause the computer has it as binary. If it IS an integer, then dealing with it in hex is trivial, since every byte in the integer is two digits of Hex, so you can use the bit shift operators (<< and >>) along with bit masks to get any single byte from the integer. If it is an integer, you just need to AND with &HFFFF, which will get the last two bytes (6CED in your example). Whether you see those bytes as decimal or hex is up to you. Still, it seems like you might be getting a string rather than an integer, in which case you first have to convert the string to an integer with CLng().

EDIT: I guess I was pretty slow, but ended up with the final example that Sitten gave. I'd certainly convert the string to a Long, then mask off the last two bytes, as he showed in his final snippet.  Reply With Quote

4. ## Re: Decimal Conversion

Getting 000225 from the reader in the software that we are trying to setup to read the rfid cards to clock in here at work. the field only holds 6 digits so it doesnt get the whole string the card is putting out. The software company said to remedy this is to get the card reader to output in a different format i.e last 4 bits to make sure no other users would clash from getting the same starting number sequence "000225" which there are several cards that start with these numbers. Normally in notepad the reader would output 0002256109  Reply With Quote

5. ## Re: Decimal Conversion

That doesn't tell us if either answer was useful.

That said, using correct words could help. "4 bits" can only hold up to 128 different values, just barely a 3-digit number. I'm assuming you meant "4 digits", which in hexadecimal means "16 bits", which can represent more than 65,000 values. But if you mean "4 digits" in decimal, well, that can only hold 10,000 values so long as 0000 is valid.

So if neither answer is helpful, you need to make really clear what your words mean.  Reply With Quote

6. ## Re: Decimal Conversion Originally Posted by Sitten Spynne That doesn't tell us if either answer was useful.

That said, using correct words could help. "4 bits" can only hold up to 128 different values, just barely a 3-digit number. I'm assuming you meant "4 digits", which in hexadecimal means "16 bits", which can represent more than 65,000 values. But if you mean "4 digits" in decimal, well, that can only hold 10,000 values so long as 0000 is valid.

So if neither answer is helpful, you need to make really clear what your words mean.
Well, 4-bits can only hold 16 values, not 128.
Based on his example, they are asking the RID reader to give them the number in Hex so they can get the whole number (apparently won't exceed a 24-bit value, i.e. 3 bytes, or 6 nibbles (a nibble is 1/2 a byte, that is 4-bits, i.e. a hexadecimal digit)).
If you take the bottom 4 hex digits, i.e. 2 bytes then you have a range of 0 to 65535 decimal, so a maximum of five decimal digit which will fit in the six decimal digit field he has to use.

While the result will be unique, and perhaps that is all he needs for the case he has, I would have thought that using the bottom six decimal digits would be the preference, as it would easier to correlate with the true original number.
Your reference decimal input was 0002256109, which you received as the Hex string 226CED.

If you convert the Hex String into a number, then convert the number into an 8 character string and take the last six characters, you get 256109 which is easier to correlate with your original decimal Id, compared to using the bottom 16-bits and getting 27885.
But the choice is yours.

The example below will print 256109 to where you have your debug.print output going (usually either the Immediate window, or the Output window depending on what option you've chosen for your IDE).
Code:
```  Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim idNum As Integer
Dim lastSixDigits As String

idNum = Convert.ToInt32("226CED", 16)
lastSixDigits = idNum.ToString("D8").Substring(2)
Debug.Print(lastSixDigits)

End Sub```
I was going to leave understanding the String formatting and how the Substring method worked up to the user to research if they didn't understand what the line is doing, and I pretty much explained it already, but to be more specific:

"D8" will convert a number into a string with 8 decimal digits (assuming an integer here) and will prepend leading zeros to make it eight digits if the number is less than 8 digits in length.

Substring(x) will return a substring of a string starting at index x.
So, we're skipping the first two digits (indexes 0 and 1) and returning the rest of the string (indexes 2 to 7, i.e. the last six digits).

p.s. Another advantage (beyond the easy correlation) of using the last six decimal digits rather than the bottom 4 hexadecimal digits, is you have a greater range of unique IDs, i.e. a million using six decimal digits (000000 to 999999) rather than 65536 (00000 to 65535) using the bottom four hex digits.

p.p.s A caveat, the simple conversion above assumes the original number will convert to a hex number of no more than six hex digits. If the decimal ID was large enough to exceed 6 hexadecimal digits then you would have the same situation where lower bits would be lost as the field would only be returning the most significant six hexadecimal digits.
At least being limited to six hexadecimal digits ensures your number can't exceed eight decimal digits (the range of six hexadecimal digits is 2^24, i.e. 00000000 to 16777215) so the Substring(2) will still extract the bottom six digits.

It would be safer to change the line to use the Right() method of the Strings class, rather than the Substring method of the String class, in which case the line would be like the following:
Code:
`    lastSixDigits = Strings.Right(idNum.ToString("D8"), 6)`
"D8" won't limit a string to 8 characters, it will only extend a short string to ensure it is 8 characters.
So, if you were allowed a larger hexadecimal number, like "3FFF6CED" for instance, that would convert to the decimal number 1073704173, and Substring(2) would return 73704173, an 8-digit string, not the six digit string we desired.
Using Strings.Right will always return the rightmost six digit (assuming the string is 6 characters or more, which the "D8" ensures that it is 8 characters or more).

If for some reason you had less than six characters in your input string (e.g. you didn't use "D8" to force it to have at least 8 characters), Right(str, 6) wouldn't be a function error, it would just return the full string of less than six characters. It won't pad out the string to force the output to six characters.  Reply With Quote

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Featured

Click Here to Expand Forum to Full Width