Library tutorials & articles
Number Systems
By Mitch Dusina, published on 16 Dec 2005
Page 5 of 5
- The Different Systems
- Any To Decimal
- Decimal To Any
- Any To Any
- Roman Numerals
Roman Numerals
And finally, we come to Roman Numerals. They are roughly
equivelent to something that we would write as "100 + 50 + 10 +
1". In other words, they are
baseless.
'The following are the 14 different valid letter combinations_
'for Roman Numerals
'and what they equal. It is improper (for whatever reason) to_
'say "IM = 999",
'you must say "CMXCIX".
Public Enum RomanNumerals As Integer
N = 0
I = 1
IV = 4
V = 5
IX = 9
X = 10
XL = 40
L = 50
XC = 90
C = 100
CD = 400
D = 500
CM = 900
M = 1000
End Enum
Public Function FromRomanNumeral(ByVal Number As String) As Long
Number = Number.ToUpper
Dim chrRomans() As Char = Number.ToCharArray
Dim intRomanParse(Number.Length) As Integer
Dim lRoman As Long
Dim i As Integer
Dim iCounter As Int16
'Basically, steps through the Roman Numeral string looking for
'valuesin the RomanNumerals Enum
For i = Number.Length - 1 To 0 Step -1
Select Case chrRomans(i).ToString
Case "N" '0
intRomanParse(i) = RomanNumerals.N
Case "I" '1
intRomanParse(i) = RomanNumerals.I
Case "V" '5
If i > 0 AndAlso chrRomans(i - 1).ToString = "I" Then
intRomanParse(i) = RomanNumerals.IV
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.V
End If
Case "X" '10
If i > 0 AndAlso chrRomans(i - 1).ToString = "I" Then
intRomanParse(i) = RomanNumerals.IX
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.X
End If
Case "L" '50
If i > 0 AndAlso chrRomans(i - 1).ToString = "X" Then
intRomanParse(i) = RomanNumerals.XL
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.L
End If
Case "C" '100
If i > 0 AndAlso chrRomans(i - 1).ToString = "X" Then
intRomanParse(i) = RomanNumerals.XC
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.C
End If
Case "D" '500
If i > 0 AndAlso chrRomans(i - 1).ToString = "C" Then
intRomanParse(i) = RomanNumerals.CD
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.D
End If
Case "M" '1000
If i > 0 AndAlso chrRomans(i - 1).ToString = "C" Then
intRomanParse(i) = RomanNumerals.CM
'Used if an extended digit is present since they use_
'2 letters
i -= 1
Else
intRomanParse(i) = RomanNumerals.M
End If
Case Else 'Not a digit
Throw New Exception(Number & " is not a valid Roman_
Numeral because it contains the symbol:_
" & chrRomans(i).ToString & ".")
End Select
Next
For i = 0 To Number.Length
lRoman += intRomanParse(i)
Next
Return lRoman
End Function
Public Function ToRomanNumeral(ByVal Number As Long) As String
Dim strRoman As String
Dim intM, intCM, intD, intCD, intC, intXC, intL, intXL, intX,_
intIX, intV, intIV, intI As Short
Dim i As Short
If Number = 0 Then Return "N"
'How many integral times does "M" go into the number?
intM = Number \ RomanNumerals.M
Number -= intM * RomanNumerals.M
'How many integral times does "CM" go into the number?
intCM = Number \ RomanNumerals.CM
Number -= intCM * RomanNumerals.CM
'How many integral times does "D" go into the number?
intD = Number \ RomanNumerals.D
Number -= intD * RomanNumerals.D
'How many integral times does "CD" go into the number?
intCD = Number \ RomanNumerals.CD
Number -= intCD * RomanNumerals.CD
'How many integral times does "C" go into the number?
intC = Number \ RomanNumerals.C
Number -= intC * RomanNumerals.C
'How many integral times does "XC" go into the number?
intXC = Number \ RomanNumerals.XC
Number -= intXC * RomanNumerals.XC
'How many integral times does "L" go into the number?
intL = Number \ RomanNumerals.L
Number -= intL * RomanNumerals.L
'How many integral times does "XL" go into the number?
intXL = Number \ RomanNumerals.XL
Number -= intXL * RomanNumerals.XL
'How many integral times does "X" go into the number?
intX = Number \ RomanNumerals.X
Number -= intX * RomanNumerals.X
'How many integral times does "IX" go into the number?
intIX = Number \ RomanNumerals.IX
Number -= intIX * RomanNumerals.IX
'How many integral times does "V" go into the number?
intV = Number \ RomanNumerals.V
Number -= intV * RomanNumerals.V
'How many integral times does "IV" go into the number?
intIV = Number \ RomanNumerals.IV
Number -= intIV * RomanNumerals.IV
'How many integral times does "I" go into the number?
intI = Number \ RomanNumerals.I
Number -= intI * RomanNumerals.I
'Puts together all the pieces
For i = 1 To intM
strRoman &= "M"
Next
For i = 1 To intCM
strRoman &= "CM"
Next
For i = 1 To intD
strRoman &= "D"
Next
For i = 1 To intCD
strRoman &= "CD"
Next
For i = 1 To intC
strRoman &= "C"
Next
For i = 1 To intXC
strRoman &= "XC"
Next
For i = 1 To intL
strRoman &= "L"
Next
For i = 1 To intXL
strRoman &= "XL"
Next
For i = 1 To intX
strRoman &= "X"
Next
For i = 1 To intIX
strRoman &= "IX"
Next
For i = 1 To intV
strRoman &= "V"
Next
For i = 1 To intIV
strRoman &= "IV"
Next
For i = 1 To intI
strRoman &= "I"
Next
Return strRoman
End Function
'This function will take an incorrectly formated Roman Numeral and_
'return it in it's corrected form ("CMXCIXVIII" becomes "MVII")
Public Function CorrectRomanNumeral(ByVal Number As String) As String
Dim lRoman As Long = FromRomanNumeral(Number)
Return ToRomanNumeral(lRoman)
End Function
Related articles
Related discussion
-
Run-time error '91'
by converter2009 (1 replies)
-
VB6 Runtime error 381 subsript out of range Error
by Uncle (2 replies)
-
passing and reading parameters from using Shell
by jigartoliya (0 replies)
-
Convert C++ code to VB6
by mawcot (4 replies)
-
listbox scrollbar
by Dennijr (10 replies)
Related podcasts
-
Christian Beauclair
14 mai 2008 (�mission #0074) ::.Christian Beauclair: Stratégies de migration VB6 vers .NET Nous discutons avec Christian Beauclair des stratégies de migration VB6 vers .NET. Entre autres, nous discutons comment utiliser le "VB 6 Code Advisor" et le "Interop Forms Toolkit" pour ajouter la puiss...
It looks good, the only thing I can spot is the line where you catch the Exception. Not finding an extended numeral is expected (and common at that), so an Exception shouldn't be used to control the flow of code.
Although I can't think of an easy way around it since they removed Enum.TryParse (2.0 and later I think).
private int ParseRomanNumeral(string numeral)
{
numeral = numeral.ToUpper();
char[] characters = numeral.ToCharArray();
int[] parseBuf = new int[numeral.Length];
int result = 0;
bool bSkip = false;
for (int i = numeral.Length - 1; i >= 0; i--)
{
if (bSkip)
{
bSkip = false; // Skip this digit because it is part of a 2-digit numeral
continue;
}
parseBuf[i] = (int)Enum.Parse(typeof(RomanNumerals), characters[i].ToString());
if (parseBuf[i] % 5 == 0 && i > 0)
{
string extended = characters[i-1].ToString() + characters[i].ToString();
try
{
parseBuf[i] = (int)Enum.Parse(typeof(RomanNumerals), extended);
bSkip = true;
}
catch(ArgumentException)
{
// Ignore this exception. It just means we didn't find an extended numeral
}
}
}
for (int i = 0; i < numeral.Length; i++)
{
result += parseBuf[i];
}
return result;
}
private string ConvertToRomanNumeral(int num)
{
string sResult = "";
sResult = Enum.GetName(typeof(RomanNumerals), num);
if (sResult == null)
{
string[] names = Enum.GetNames(typeof(RomanNumerals));
int[] vals = (int[])Enum.GetValues(typeof(RomanNumerals));
for (int i = names.Length - 1; i > 0; i--) // Don't process the 0th element, since it is 0 and results in bad math
{
int temp = num / vals[i];
num -= temp * vals[i];
for (int j = 0; j < temp; j++)
{
sResult += names[i];
}
}
}
return sResult;
}
This thread is for discussions of Number Systems.