Since there is no real way to express
G1 Septendecimal in Visual
Studio, we use the String variable type to hold a textual
representation of it. Regardless of the base, there is a general
equation for converting it to decimal by calculating each character's
base weight and then adding the individual values together.
Public Function AnyToDecimal(ByVal Number As String, ByVal Base As_
Short) As Long
Dim lDecimalOutput As Long
Dim IsNegative As Boolean
Dim i As Short
'Lower case a-z may be used to represent something different
'then their upper case counterparts if desired<
Number = Number.ToUpper()
'Roman Numerals (Roman Numerals have no Base technically
'and are really just an addition problem which needs to be
'dealt with in a different way)
If Base = 0 Then
Return FromRomanNumeral(Number)
End If
'Determine if the string is negative
If Number.StartsWith("-") = True Then
IsNegative = True
Number = Number.Replace("-", "")
End If
'Remove Invalid Characters
Dim chrTemp() As Char = Number.ToCharArray
Number = ""
For i = 0 To chrTemp.Length - 1
'Only accept numbers and characters
If (IsNumber(chrTemp(i).ToString) = True) Or_
(IsLetter(chrTemp(i).ToString) = True) Then
Number &= chrTemp(i).ToString
End If
Next
Dim chrNumberSplit() As Char = Number.ToCharArray
Dim lNumberSplit(chrNumberSplit.GetUpperBound(0)) As Long
'Supported Bases (1-9 A-Z currently. This behavior can be_
'modified to allow "AA" to come after "Z", etc.)
If Base < 0 Then Throw New Exception("Starting Base must be_
Greater Than or Equal to 0.")
'Add the value of each symbol to an array (9 = 9, A = 10,_
'B = 11, etc.)
For i = 0 To chrNumberSplit.GetUpperBound(0)
If Char.IsNumber(chrNumberSplit(i)) Then
lNumberSplit(i) = Int(chrNumberSplit(i).ToString)
Else
'Convert letters to numbers (A = 10, etc.)
lNumberSplit(i) = Asc(chrNumberSplit(i)) - 55
End If
'Checks for "overflow" chacacters (Base 1 is different_
'because the '1' chacter is used instead of the 0)
If lNumberSplit(i) > Base - 1 AndAlso Base <> 1 Then
Throw New Exception(chrNumberSplit(i) & " is not a valid_
character in a " & GetBaseName(Base) & " number system.")
ElseIf Base = 1 AndAlso lNumberSplit(i) <> 1 Then
Throw New Exception(chrNumberSplit(i) & " is not a valid_
character in a " & GetBaseName(Base) & " number system.")
End If
Next
Try
'Calculate the Base weight of each array item
For i = 0 To chrNumberSplit.GetUpperBound(0)
lNumberSplit(i) = lNumberSplit(i) * Base ^_
(chrNumberSplit.GetUpperBound(0) - i)
Next
'Add the weighted values together to produce a Decimal_
'representation
For i = 0 To chrNumberSplit.GetUpperBound(0)
lDecimalOutput += lNumberSplit(i)
Next
'If the original number was negative, reflect it
If IsNegative = True Then
lDecimalOutput *= -1
End If
Catch
Throw New Exception("[" & Number & "] " & GetBaseName(Base)_
& " requires more than 64-bits in Decimal form to represent_
(Overflow).")
End Try
Return lDecimalOutput
End Function
The preceding code requires these self explainitry Functions:
Public Function IsNumber(ByVal TestString As String) As Boolean
Dim chrString() As Char = TestString.ToCharArray
Dim i0, i9 As Short
Dim i As Integer
i0 = Asc("0")
i9 = Asc("9")
For i = 0 To TestString.Length - 1
If (Asc(chrString(i)) < i0 Or Asc(chrString(i)) > i9) Then
Return False
Exit Function
End If
Next
Return True
End Function
Public Function IsLetter(ByVal TestString As String) As Boolean
Dim chrString() As Char = TestString.ToCharArray
Dim iLowerA, iLowerZ, iUpperA, iUpperZ As Short
Dim i As Integer
iLowerA = Asc("a")
iLowerZ = Asc("z")
iUpperA = Asc("A")
iUpperZ = Asc("Z")
For i = 0 To TestString.Length - 1
If (Asc(chrString(i)) >= iLowerA And Asc(chrString(i)) <= iLowerZ)_
Or (Asc(chrString(i)) >= iUpperA And Asc(chrString(i)) <= iUpperZ) Then
Else
Return False
Exit Function
End If
Next
Return True
End Function
Comments