BLOG.CSHARPHELPER.COM: Make extension methods that convert numbers between Arabic and Roman numerals in C#
Make extension methods that convert numbers between Arabic and Roman numerals in C#
The following extension method converts a Roman numeral into its Arabic equivalent.
// Return the Arabic version of this number. public static int ToArabic(this string roman_number) { roman_number = roman_number.ToUpper(); int arabic_number = 0; int old_value = 1000;
// Loop through the Roman characters. for (int i = 0; i < roman_number.Length; i++) { // See what the next character is worth. char ch = roman_number[i]; int new_value = 0; switch (ch) { case 'I': new_value = 1; break; case 'V': new_value = 5; break; case 'X': new_value = 10; break; case 'L': new_value = 50; break; case 'C': new_value = 100; break; case 'D': new_value = 500; break; case 'M': new_value = 1000; break; }
// See if this value is bigger than the previous one. if (new_value > old_value) { // new_value > old_value. // Add this value to the result // and subtract the previous one twice. arabic_number += new_value - 2 * old_value; } else { // new_value <= old_value. Add it to the result. arabic_number += new_value; }
old_value = new_value; }
if ((arabic_number < 1) || (arabic_number > 3999)) throw new ArgumentOutOfRangeException( "roman_number", "Roman number must be between I (1) and MMMCMXCIX (3999)");
return arabic_number; }
The code examines each digit in the Roman numeral, converting each into its Roman equivalent: I=1, V=5, X=10, L=50, C=100, D=500, M=1000.
If a digit has value greater than the previous one, then combination represents a subtraction. For example, IX means X minus I. Because the previous digit has already been added to the result, the code subtracts it twice and adds the new digit. For IX, when the code gets to the X, the I has already been added so the result is 1. The code then subtracts 2 * 1 and adds 10 to get: 1 - 2 * 1 + 10 = 9.
The RomanDigits method shown in the following code returns Roman numeral digits representing an Arabic digit.
// Return the Roman numeral digits for the arabic digit. // The ten_char, five_char, and one_char parameters // give the Roman digits representing 10, 5, and 1 // for this power of ten. For example, 10/5/1 = X/V/I // and 100/50/10 = C/L/X. private static string RomanDigits(int arabic_digit, char ten_char, char five_char, char one_char) { // Bounds checking. Debug.Assert(arabic_digit >= 0 && arabic_digit <= 9);
if (arabic_digit <= 3) return new string(one_char, arabic_digit); if (arabic_digit == 4) return one_char.ToString() + five_char.ToString(); if (arabic_digit == 5) return five_char.ToString(); if (arabic_digit <= 8) return five_char + new string(one_char, arabic_digit - 5); return one_char.ToString() + ten_char.ToString(); }
The method's input parameters ten_char, five_char, and one_char are the Roman number characters used to represent 10, 5, and 1 at the current power of ten. For example, if the Arabic digit represents tens, then these should be C (10 * ten), L (5 * ten), and X (1 * ten).
The code simply examines the Arabic digit and returns the appropriate Roman equivalent.
The following ToRoman extension method uses the RomanDigits method to convert an Arabic number into its Roman equivalent.
// Convert Arabic to Roman. This only works up to 3999. public static string ToRoman(this int arabic_number) { if ((arabic_number < 1) || (arabic_number > 3999)) throw new ArgumentOutOfRangeException( "arabic_number", "Arabic number must be between 1 and 3999");
// Thousands. string result = ""; int digit = arabic_number / 1000; arabic_number = arabic_number % 1000; result += new string('M', digit);
This code pulls out the Arabic number's thousands, hundreds, tens, and ones digits. It uses the RomanDigits method to find the Roman numeral equivalent for each and adds them to the result.
Comments