I\'m trying to write a function that converts numbers to roman numerals. This is my code so far; however, it only works with numbers that are less than 400. Is there a quick
This version doesn't "cheat" as others: it generates internally the "base" table with all the "base" "composable" numbers. For lazyness I'm using Tuple
s, instead of creating specialized classes. If you don't have C# 4.0, you can replace Tuple<>
with KeyValuePair<>
, Item1
with Key
and Item2
with Value
.
static Tuple>, int> GenerateBaseNumbers()
{
const string letters = "IVXLCDM";
var tuples = new List>();
Tuple subtractor = null;
int num = 1;
int maxNumber = 0;
for (int i = 0; i < letters.Length; i++)
{
string currentLetter = letters[i].ToString();
if (subtractor != null)
{
tuples.Add(Tuple.Create(subtractor.Item1 + currentLetter, num - subtractor.Item2));
}
tuples.Add(Tuple.Create(currentLetter, num));
bool isEven = i % 2 == 0;
if (isEven)
{
subtractor = tuples[tuples.Count - 1];
}
maxNumber += isEven ? num * 3 : num;
num *= isEven ? 5 : 2;
}
return Tuple.Create((IList>)new ReadOnlyCollection>(tuples), maxNumber);
}
static readonly Tuple>, int> RomanBaseNumbers = GenerateBaseNumbers();
static string FromNumberToRoman(int num)
{
if (num <= 0 || num > RomanBaseNumbers.Item2)
{
throw new ArgumentOutOfRangeException();
}
StringBuilder sb = new StringBuilder();
int i = RomanBaseNumbers.Item1.Count - 1;
while (i >= 0)
{
var current = RomanBaseNumbers.Item1[i];
if (num >= current.Item2)
{
sb.Append(current.Item1);
num -= current.Item2;
}
else
{
i--;
}
}
return sb.ToString();
}
static void Main(string[] args)
{
for (int i = 1; i <= RomanBaseNumbers.Item2; i++)
{
var calc = FromNumberToRoman(i);
Console.WriteLine("{1}", i, calc);
}
}