Converting integers to roman numerals

前端 未结 29 2401
走了就别回头了
走了就别回头了 2020-12-02 09:16

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

29条回答
  •  [愿得一人]
    2020-12-02 09:32

    This version doesn't "cheat" as others: it generates internally the "base" table with all the "base" "composable" numbers. For lazyness I'm using Tuples, 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);
        }
    }
    

提交回复
热议问题