Converting integers to roman numerals

前端 未结 29 2296
走了就别回头了
走了就别回头了 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:35

    Try this, simple and compact:

    public static string ToRoman(int number)
    {
        if ((number < 0) || (number > 3999)) throw new ArgumentOutOfRangeException("insert value betwheen 1 and 3999");
        if (number < 1) return string.Empty;            
        if (number >= 1000) return "M" + ToRoman(number - 1000);
        if (number >= 900) return "CM" + ToRoman(number - 900); 
        if (number >= 500) return "D" + ToRoman(number - 500);
        if (number >= 400) return "CD" + ToRoman(number - 400);
        if (number >= 100) return "C" + ToRoman(number - 100);            
        if (number >= 90) return "XC" + ToRoman(number - 90);
        if (number >= 50) return "L" + ToRoman(number - 50);
        if (number >= 40) return "XL" + ToRoman(number - 40);
        if (number >= 10) return "X" + ToRoman(number - 10);
        if (number >= 9) return "IX" + ToRoman(number - 9);
        if (number >= 5) return "V" + ToRoman(number - 5);
        if (number >= 4) return "IV" + ToRoman(number - 4);
        if (number >= 1) return "I" + ToRoman(number - 1);
        throw new ArgumentOutOfRangeException("something bad happened");
    }
    
    0 讨论(0)
  • 2020-12-02 09:38

    Far too late, probably you already solved this, however this is an algorithm which can do the trick for you as well.

    Before you start, you could simply do the analysis on Roman literals. For the known ASCII set, only values between 0 and 4000 are supported. If you like to go beyond, you could define your own roman literal then.

    Before we start, we know that with the given range above, we can form a roman string from seven occurrences of Roman Literals (I,V,X,L,C,D and M).

    Therefore we start with a simple look-up table, based on indices which are calculated in another function. Unknown indices are returned as a white-space character. As I wrote above, one might add additional characters when needed:

        /// <summary>
        /// Helper method that looks up a given index to it's roman value.
        /// </summary>
        /// <param name="decimalValue"></param>
        /// <returns>The roman literal corresponding to it's index</returns>
        private char DecimalToRoman(int index)
        {
            switch (index)
            {
                case 1: return 'I';
                case 2: return 'V';
                case 3: return 'X';
                case 4: return 'L';
                case 5: return 'C';
                case 6: return 'D';
                case 7: return 'M';
                default: return ' ';
            }
        }
    

    The real conversion will happen here:

        private string ConvertToRoman(string input)
        {
            int index = 0;
            string output = "";
    
            for (int i = 0; i < input.Length; i++)
            {
                //Some magic here, this formula will calculate the correct starting
                //index of the roman literal to find in the look-up table.
                //Since units, tens and hundreds (up to thousand) can be formed of
                //three roman literals, we need three indices for looking up the
                //correct roman literal.
                index = 2 * (input.Length - (i + 1)) + 1;
    
                char digit1 = DecimalToRoman(index);
                char digit2 = DecimalToRoman(index + 1);
                char digit3 = DecimalToRoman(index + 2);
    
                int originalValue = System.Convert.ToInt32(input[i] - '0');
    
                switch (originalValue)
                {
                    case 1:
                    case 2:
                    case 3: for (int j = 0; j < originalValue; j++)
                            output += digit1.ToString();
                        break;
                    case 4: output += digit1.ToString() + digit2.ToString();
                        break;
                    case 5: output += digit2.ToString();
                        break;
                    case 6:
                    case 7:
                    case 8: output += digit2.ToString();
                        for (int j = 0; j < originalValue - 5; j++)
                            output += digit1.ToString();
                        break;
                    case 9: output += digit1.ToString() + digit3.ToString();
                        break;
                }              
            }
            return output;
        }
    

    That is it. If you look for more OO Designed approaches, please accept the answers above this post. There are just a lot of ways to solve this approach.

    EDIT: Note that this solution does not cheat (just looking up all occurences of roman literals) as well :)

    0 讨论(0)
  • 2020-12-02 09:38
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Enter the number\n");
                int num = int.Parse(Console.ReadLine());
                ToRomanNumber tr = new ToRomanNumber();
                string opt=tr.ToRoman(num);
                Console.WriteLine(opt);
            }
        }
        class ToRomanNumber
        {
            string s = "";
    
            public string ToRoman(int number)
            {
    
                if ((number < 0) || (number > 3999))
                {
                    s = s + "Invalid Input";
                }
                if (number < 1) return s;
                if (number >= 1000) { s = s + "M"; ToRoman(number - 1000);}
                if (number >= 900){ s = s + "CM";ToRoman(number - 900);}
                if (number >= 500){ s = s + "D"; ToRoman(number - 500);}
                if (number >= 400){ s = s + "CD"; ToRoman(number - 400);}
                if (number >= 100){ s = s + "C"; ToRoman(number - 100);}
                if (number >= 90){ s = s + "XC"; ToRoman(number - 90);}
                if (number >= 50){ s = s + "L";ToRoman(number - 50);}
                if (number >= 40){ s = s + "XL";ToRoman(number - 40);}
                if (number >= 10){ s = s + "X"; ToRoman(number - 10); }
                if (number >= 9) { s = s + "IX"; ToRoman(number - 9); }
                if (number >= 5) { s = s + "V"; ToRoman(number - 5); }
                if (number >= 4) { s = s + "IV"; ToRoman(number - 4); }
                if (number >= 1) { s = s + "I"; ToRoman(number - 1);}
                return s;
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-02 09:39
     public static int pairConversion(int dec, int lastNum, int lastDec)
        {
            if (lastNum > dec)
                return lastDec - dec;
            else return lastDec + dec;
        }
    
        public static int ConvertRomanNumtoInt(string strRomanValue)
        {
            var dec = 0;
            var lastNum = 0;
            foreach (var c in strRomanValue.Reverse())
            {
                switch (c)
                {
                    case 'I':
                        dec = pairConversion(1, lastNum, dec);
                        lastNum = 1;
                        break;
                    case 'V':
                        dec=pairConversion(5,lastNum, dec);
                        lastNum = 5;
                        break;
                    case 'X':
                        dec = pairConversion(10, lastNum, dec);
                        lastNum = 10;
                        break;
                    case 'L':
                        dec = pairConversion(50, lastNum, dec);
                        lastNum = 50;
                        break;
                    case 'C':
                        dec = pairConversion(100, lastNum, dec);
                        lastNum = 100;
                        break;
                    case 'D':
                        dec = pairConversion(500, lastNum, dec);
                        lastNum = 500;
                        break;
                    case 'M':
                        dec = pairConversion(1000, lastNum, dec);
                        lastNum = 1000;
                        break;
                }
            }
            return dec;
    
        }
    

    It would be easier if you reverse the roman numerals to handle the case like XIV. The code is refer from this blog.

    0 讨论(0)
  • 2020-12-02 09:39

    In javascript

    function toRoman(num) {
        var listOfNum = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
        var listOfRoman = ['M', 'CM', 'D', 'CD', "C", 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
    
        var numToRoman = '';
        for (let i = 0; i < listOfNum.length; i++) {
            while (num >= listOfNum[i]) {
                numToRoman += listOfRoman[i];
                num -= listOfNum[i];
            }
        }
        return numToRoman;
    }
    
    
    0 讨论(0)
  • 2020-12-02 09:40

    A neat, quick and straightforward solution

    function convertToRoman(num) {
    
      //Roman numerals to have <= 3 consecutive characters, the distances between deciaml values conform to this
      var decimalValue = [ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ];
      var romanNumeral = [ 'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I' ];
      var num_cp = num; // copy the function parameter into num_cp
      var result = '';
    
      for (var i=0; i < decimalValue.length; i++){ //itarate through array of decimal values
          //iterate more to find values not explicitly provided in the decimalValue array
        while (decimalValue[i] <= num_cp){
          result += romanNumeral[i];
          num_cp -= decimalValue[i];
        }
      }
      return result;
    }
    
    convertToRoman(477);
    
    0 讨论(0)
提交回复
热议问题