class RomanNumber
{
/// <summary>
/// The possible characters used to represent a single digit in a Roman number.
/// Example: For tens digit, Ten = C (100), Five = L (50), One = X (10)
/// </summary>
class RomanDigit
{
public char Ten { get; set; }
public char Five { get; set; }
public char One { get; set; }
}
#region Constants
static List<RomanDigit> RomanDigits = new List<RomanDigit>()
{
new RomanDigit() {Ten = 'X', Five = 'V', One = 'I'}, // Ones place
new RomanDigit() {Ten = 'C', Five = 'L', One = 'X'}, // Tens place
new RomanDigit() {Ten = 'M', Five = 'D', One = 'C'}, // Hundreds place
new RomanDigit() {One = 'M'}, // Thousands place
};
static int MAX = 3999;
static int MIN = 0;
#endregion
/// <summary>
/// Converts an Arabic number to a Roman number by converting one digit at a time.
/// </summary>
/// <param name="arabic"></param>
/// <returns></returns>
public static string ToRoman(int arabic)
{
if (arabic > MAX || arabic < MIN) throw new ArgumentOutOfRangeException("Arabic number must between 0 and 3999.");
string roman = "";
int decimalPlace = 0; // Start at 10^0 (ones place)
while (arabic > 0)
{
// Get lowest digit
int currentDigit = arabic % 10;
// Add converted string to output
RomanDigit digit = RomanDigits[decimalPlace];
if (currentDigit % 5 == 4) // Special case for 4 and 9, print "One" followed by "Five" or "Ten".
roman = string.Format("{0}{1}", digit.One, (currentDigit == 9) ? digit.Ten : digit.Five) + roman;
else // If currentDigit > 5, print "Five". Then print "One" several times until done.
roman = string.Format("{0}{1}", (currentDigit >= 5) ? digit.Five.ToString() : "", new String(digit.One, currentDigit % 5)) + roman;
// Next loop iteration
arabic /= 10; // Divide by 10 to get next digit
decimalPlace++; // Go to next RomanDigit
}
return roman;
}
}