Basic program to convert integer to Roman numerals?

Question:

I’m trying to write a code that converts a user-inputted integer into its Roman numeral equivalent. What I have so far is:

screenshot of my code

The point of the generate_all_of_numeral function is so that it creates a string for each specific numeral. For example, generate_all_of_numeral(2400, 'M', 2000) would return the string 'MM'.

I’m struggling with the main program. I start off finding the Roman numeral count for M and saving that into the variable M. Then I subtract by the number of M’s times the symbol value to give me the next value to work with for the next largest numeral.

Any nod to the right direction? Right now my code doesn’t even print anything.

Asked By: skybreaker

||

Answers:

You have to make the symbolCount a global variable. And use () in print method.

Answered By: Gotrank

When you use the def keyword, you just define a function, but you don’t run it.

what you’re looking for is something more like this:

def generate_all_numerals(n): 
...

def to_roman(n):
...

print "This program ..."
n = raw_input("Enter...")

print to_roman(n)

welcome to python 🙂

Answered By: bgnalm

One of the best ways to deal with this is using the divmod function. You check if the given number matches any Roman numeral from the highest to the lowest. At every match, you should return the respective character.

Some numbers will have remainders when you use the modulo function, so you also apply the same logic to the remainder. Obviously, I’m hinting at recursion.

See my answer below. I use an OrderedDict to make sure that I can iterate “downwards” the list, then I use a recursion of divmod to generate matches. Finally, I join all generated answers to produce a string.

from collections import OrderedDict

def write_roman(num):

    roman = OrderedDict()
    roman[1000] = "M"
    roman[900] = "CM"
    roman[500] = "D"
    roman[400] = "CD"
    roman[100] = "C"
    roman[90] = "XC"
    roman[50] = "L"
    roman[40] = "XL"
    roman[10] = "X"
    roman[9] = "IX"
    roman[5] = "V"
    roman[4] = "IV"
    roman[1] = "I"

    def roman_num(num):
        for r in roman.keys():
            x, y = divmod(num, r)
            yield roman[r] * x
            num -= (r * x)
            if num <= 0:
                break

    return "".join([a for a in roman_num(num)])

Taking it for a spin:

num = 35
print write_roman(num)
# XXXV

num = 994
print write_roman(num)
# CMXCIV

num = 1995
print write_roman(num)
# MCMXCV

num = 2015
print write_roman(num)
# MMXV
Answered By: WGS

The approach by Laughing Man works. Using an ordered dictionary is clever. But his code re-creates the ordered dictionary every time the function is called, and within the function, in every recursive call, the function steps through the whole ordered dictionary from the top. Also, divmod returns both the quotient and the remainder, but the remainder is not used. A more direct approach is as follows.

def _getRomanDictOrdered():
    #
    from collections import OrderedDict
    #
    dIntRoman = OrderedDict()
    #
    dIntRoman[1000] = "M"
    dIntRoman[900] = "CM"
    dIntRoman[500] = "D"
    dIntRoman[400] = "CD"
    dIntRoman[100] = "C"
    dIntRoman[90] = "XC"
    dIntRoman[50] = "L"
    dIntRoman[40] = "XL"
    dIntRoman[10] = "X"
    dIntRoman[9] = "IX"
    dIntRoman[5] = "V"
    dIntRoman[4] = "IV"
    dIntRoman[1] = "I"
    #
    return dIntRoman

_dIntRomanOrder = _getRomanDictOrdered() # called once on import

def getRomanNumeralOffInt( iNum ):
    #
    lRomanNumerals = []
    #
    for iKey in _dIntRomanOrder:
        #
        if iKey > iNum: continue
        #
        iQuotient = iNum // iKey
        #
        if not iQuotient: continue
        #
        lRomanNumerals.append( _dIntRomanOrder[ iKey ] * iQuotient )
        #
        iNum -= ( iKey * iQuotient )
        #
        if not iNum: break
        #
    #
    return ''.join( lRomanNumerals )

Checking the results:

>>> getRomanNumeralOffInt(35)
'XXXV'
>>> getRomanNumeralOffInt(994)
'CMXCIV'
>>> getRomanNumeralOffInt(1995)
'MCMXCV'
>>> getRomanNumeralOffInt(2015)
'MMXV'
Answered By: Rick Graves
 """
# This program will allow the user to input a number from 1 - 3999 (in english) and will translate it to Roman numerals.
# sources: http://romannumerals.babuo.com/roman-numerals-100-1000
Guys the reason why I wrote this program like that so it becomes readable for everybody. 
Let me know if you have any questions... 
"""
while True:
    try:
        x = input("Enter a positive integer from 1 - 3999 (without  spaces) and this program will translated to Roman numbers: ")
        inttX = int(x)
        if (inttX) == 0 or 0 > (inttX):
            print("Unfortunately, the  smallest number that you can enter is 1 ")
        elif (inttX) > 3999:
            print("Unfortunately, the  greatest number that you can enter is 3999")
        else:
            if len(x) == 1:
                if inttX == 1:
                    first = "I"
                elif inttX == 2:
                    first = "II"
                elif inttX == 3:
                    first = "III"
                elif inttX == 4:
                    first = "IV"
                elif inttX == 5:
                    first = "V"
                elif inttX == 6:
                    first = "VI"
                elif inttX == 7:
                    first = "VII"
                elif inttX == 8:
                    first = "VIII"
                elif inttX == 9:
                    first = "IX"
                print(first)
                break
            if len(x) == 2:
                a = int(x[0])
                b = int(x[1])
                if a == 0:
                    first = ""
                elif a == 1:
                    first = "X"
                elif a == 2:
                    first = "XX"
                elif a == 3:
                    first = "XXX"
                elif a == 4:
                    first = "XL"
                elif a == 5:
                    first = "L"
                elif a == 6:
                    first = "LX"
                elif a == 7:
                    first = "LXX"
                elif a == 8:
                    first = "LXXX"
                elif a == 9:
                    first = "XC"

                if b == 0:
                    first1 = "0"
                if b == 1:
                    first1 = "I"
                elif b == 2:
                    first1 = "II"
                elif b == 3:
                    first1 = "III"
                elif b == 4:
                    first1 = "IV"
                elif b == 5:
                    first1 = "V"
                elif b == 6:
                    first1 = "VI"
                elif b == 7:
                    first1 = "VII"
                elif b == 8:
                    first1 = "VIII"
                elif b == 9:
                    first1 = "IX"
                print(first + first1)
                break
            if len(x) == 3:
                a = int(x[0])
                b = int(x[1])
                c = int(x[2])
                if a == 0:
                    first12 = ""
                if a == 1:
                    first12 = "C"
                elif a == 2:
                    first12 = "CC"
                elif a == 3:
                    first12 = "CCC"
                elif a == 4:
                    first12 = "CD"
                elif a == 5:
                    first12 = "D"
                elif a == 6:
                    first12 = "DC"
                elif a == 7:
                    first12 = "DCC"
                elif a == 8:
                    first12 = "DCCC"
                elif a == 9:
                    first12 = "CM"

                if b == 0:
                    first = ""
                elif b == 1:
                    first = "X"
                elif b == 2:
                    first = "XX"
                elif b == 3:
                    first = "XXX"
                elif b == 4:
                    first = "XL"
                elif b == 5:
                    first = "L"
                elif b == 6:
                    first = "LX"
                elif b == 7:
                    first = "LXX"
                elif b == 8:
                    first = "LXXX"
                elif b == 9:
                    first = "XC"

                if c == 1:
                    first1 = "I"
                elif c == 2:
                    first1 = "II"
                elif c == 3:
                    first1 = "III"
                elif c == 4:
                    first1 = "IV"
                elif c == 5:
                    first1 = "V"
                elif c == 6:
                    first1 = "VI"
                elif c == 7:
                    first1 = "VII"
                elif c == 8:
                    first1 = "VIII"
                elif c == 9:
                    first1 = "IX"
                print(first12 + first + first1)
                break

            if len(x) == 4:
                a = int(x[0])
                b = int(x[1])
                c = int(x[2])
                d = int(x[3])
                if a == 0:
                    first1 = ""
                if a == 1:
                    first1 = "M"
                elif a == 2:
                    first1 = "MM"
                elif a == 3:
                    first1 = "MMM"

                if b == 0:
                    first12 = ""
                if b == 1:
                    first12 = "C"
                elif b == 2:
                    first12 = "CC"
                elif b == 3:
                    first12 = "CCC"
                elif b == 4:
                    first12 = "CD"
                elif b == 5:
                    first12 = "D"
                elif b == 6:
                    first12 = "DC"
                elif b == 7:
                    first12 = "DCC"
                elif b == 8:
                    first12 = "DCCC"
                elif b == 9:
                    first12 = "CM"

                if c == 0:
                    first3 = ""
                elif c == 1:
                    first3 = "X"
                elif c == 2:
                    first3 = "XX"
                elif c == 3:
                    first3 = "XXX"
                elif c == 4:
                    first3 = "XL"
                elif c == 5:
                    first3 = "L"
                elif c == 6:
                    first3 = "LX"
                elif c == 7:
                    first3 = "LXX"
                elif c == 8:
                    first3 = "LXXX"
                elif c == 9:
                    first3 = "XC"

                if d == 0:
                    first = ""
                elif d == 1:
                    first = "I"
                elif d == 2:
                    first = "II"
                elif d == 3:
                    first = "III"
                elif d == 4:
                    first = "IV"
                elif d == 5:
                    first = "V"
                elif d == 6:
                    first = "VI"
                elif d == 7:
                    first = "VII"
                elif d == 8:
                    first = "VIII"
                elif d == 9:
                    first = "IX"
                print(first1 + first12 + first3 + first)
                break
    except ValueError:
        print(" Please enter a positive integer! ")
Answered By: Mohammad Mahjoub

Here is another way, without division:

num_map = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
           (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]


def num2roman(num):

    roman = ''

    while num > 0:
        for i, r in num_map:
            while num >= i:
                roman += r
                num -= i

    return roman

# test 
>>> num2roman(2242)
'MMCCXLII'

Update see the execution visualized

Answered By: Aziz Alto

Only 1 – 999

while True:

 num = input()
 def val(n):
    if n == 1:
        rom = 'I'
        return rom
    if n == 4:
        rom = 'IV'
        return rom
    if n == 5:
        rom = 'V'
        return rom
    if n == 9:
        rom = 'IX'
        return rom
    if n == 10:
        rom = 'X'
        return rom
    if n == 40:
        rom = 'XL'
        return rom
    if n == 50:
        rom = 'L'
        return rom
    if n == 90:
        rom = 'XC'
        return rom
    if n == 100:
        rom = 'C'
        return rom
    if n == 400:
        rom = 'CD'
        return rom
    if n == 500:
        rom = 'D'
        return rom
    if n == 900:
        rom = 'CM'
        return rom

 def lastdigit(num02):
    num02 = num % 10
    num03 = num % 5
    if 9 > num02 > 5:
        return str('V' + 'I'*num03)
    elif num02 < 4:
        return str('I'*num03)
    else:
        return str(val(num02))

 k3 = lastdigit(num)

 def tensdigit(num12):
    num12 = num % 100 - num % 10
    num13 = num % 50
    if 90 > num12 > 50:
        return str('L' + 'X'*(num13/10))
    elif num12 < 40:
        return str('X'*(num13/10))
    else:
        return str(val(num12))

 k2 = tensdigit(num)

 def hundigit(num112):
    num112 = (num % 1000 - num % 100)
    num113 = num % 500
    if 900 > num112 > 500:
        return str('D' + 'C'*(num113/100))
    elif num112 < 400:
        return str('C'*(num113/100))
    else:
        return str(val(num112))

 k1 = hundigit(num)

 print '%s%s%s' %(k1,k2,k3)
Answered By: user7122277

Another way to do this. separating out processing of number starting with 4 , 9 and others. it can be simplified further

def checkio(data):
romans = [("I",1),("V",5),("X",10),("L",50),("C",100),("D",500),("M",1000)]
romans_rev = list(sorted(romans,key = lambda x: -x[1]))
def process_9(num,roman_str):
    for (k,v) in romans:
        if (v > num):
            current_roman = romans[romans.index((k,v))]
            prev_roman = romans[romans.index((k,v)) - 2]
            roman_str += (prev_roman[0] + current_roman[0])
            num -= (current_roman[1] - prev_roman[1])
            break
    return num,roman_str
def process_4(num,roman_str):
    for (k,v) in romans:
        if (v > num):
            current_roman = romans[romans.index((k,v))]
            prev_roman = romans[romans.index((k,v)) - 1]
            roman_str += (prev_roman[0] + current_roman[0])
            num -= (current_roman[1] - prev_roman[1])
            break
    return num,roman_str
def process_other(num,roman_str):
    for (k,v) in romans_rev:
        div = num // v
        if ( div != 0 and num > 0 ):
            roman_str += k * div
            num -= v * div
            break
    return num,roman_str
def get_roman(num):
    final_roman_str = ""
    while (num > 0):
        if (str(num).startswith('4')):
            num,final_roman_str = process_4(num,final_roman_str)
        elif(str(num).startswith('9')):
            num,final_roman_str = process_9(num,final_roman_str)
        else:
            num,final_roman_str = process_other(num,final_roman_str)
    return final_roman_str

return get_roman(data)


print(checkio(number))
Answered By: Linus

This is my approach

def itr(num):  
    dct = { 1: "I", 4: "IV", 5: "V", 9: "IX", 10: "X", 40: "XL", 50: "L", 90: "XC", 100: "C", 400: "CD", 500: "D", 900: "CM", 1000: "M" }
    if(num in dct):
        return dct[num]

    for i in [1000,100,10,1]:
        for j in [9*i, 5*i, 4*i, i]:
            if(num>=j):
                return itr(j) + itr(num-j) 
Answered By: cardeol
def test(num):

    try:
        if type(num) != type(1):
            raise Exception("expected integer, got %s" % type(num))
        if not 0 < num < 4000:
            raise Exception("Argument must be between 1 and 3999")
        ints = (1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1)
        nums = ('M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I')
        result = ""
        for i in range(len(ints)):
            count = int(num / ints[i])
            result += nums[i] * count
            num -= ints[i] * count
        print result
    except Exception as e:
        print e.message
Answered By: Divyang Bissa

I have observed that in most of the answers, people are storing excess notations like "IX" for 9, "XL" for 40 and so on.

This misses the main essence of Roman Conversion.

Here’s a small introduction and algorithm before I actually paste the code.

The original pattern for Roman numerals used the symbols I, V. and X (1, 5, and 10) as simple tally marks. Each marker for 1 (I) added a unit value up to 5 (V), and was then added to (V) to make the numbers from 6 to 9:

I, II, III, IIII, V, VI, VII, VIII, VIIII, X.

The numerals for 4 (IIII) and 9 (VIIII) proved problematic, and are generally replaced with IV (one less than 5) and IX (one less than 10). This feature of Roman numerals is called subtractive notation.

The numbers from 1 to 10 (including subtractive notation for 4 and 9) are expressed in Roman numerals as follows:

I, II, III, IV, V, VI, VII, VIII, IX, X.

The system being basically decimal, tens and hundreds follow the same pattern:
Thus 10 to 100 (counting in tens, with X taking the place of I, L taking the place of V and C taking the place of X):

X, XX, XXX, XL, L, LX, LXX, LXXX, XC, C. Roman Numerals – Wikipedia

So, the main logic that can derive from the above introduction is that, we would strip the positional value and perform divisions based on the values of the literals Romans used.

Let’s start the base example. We have the integral list of the literals as [10, 5, 1]

  1. 1/10 = 0.1 (not of much use)

    1/5 = 0.2 (not of much use, either)

    1/1 = 1.0 (hmm, we got something!)

    CASE 1: So, if quotient == 1, print the literal corresponding to the integer. So, the best data structure would be a dictionary. {10: "X", 5: "V", 1:"I"}

    “I” will be printed.

  2. 2/10 = 0.2

    2/5 = 0.4

    2/1 = 2

    CASE 2: So, if quotient > 1, print the literal corresponding to the integer which made it so and subtract it from the number.
    This makes it 1 and it falls to CASE 1.
    “II” is printed.

  3. 3/10 = 0.3

    3/5 = 0.6

    3/1 = 3

    So, CASE 2: “I”, CASE 2: “II” and CASE 1: “III”

  4. CASE 3: Add 1 and check if quotient == 1.

    (4+1)/10 = 0.5

    (4+1)/5 = 1

    So, this is the case where we first subtract the divisor and the number and print the literal corresponding to the result, followed by the divisor. 5-4=1, thus “IV” will be printed.

  5. (9+1)/10 == 1

    10-9=1. Print “I”, print “X”, i.e. “IX”

This extends to the tenths place and hundredths as well.

  1. (90+(10^1))/100 = 1.

    Print 100-90=”X”, followed by 100=”C”.

  2. (400+(10^2))/500 = 1.

    Print 500-400=”C”, followed by 500=”D”.

The last thing we need here is, extract the positional values. Ex: 449 should yield 400, 40, 9.

This can be made by removing the subtracting the modulo of 10^(position-1) and then taking the modulo of 10^position.

Ex: 449, position = 2: 449%(10^1) = 9 -> 449-9 -> 440%(10^2)= 40.

'''
Created on Nov 20, 2017

@author: lu5er
'''
n = int(input())
ls = [1000, 500, 100, 50, 10, 5, 1]
st = {1000:"M", 500:"D", 100:"C", 50:"L", 10:"X", 5:"V", 1:"I"}

rem = 0

# We traverse the number from right to left, extracting the position
for i in range(len(str(n)), 0, -1):
    pos = i # stores the current position
    num = (n-n%(10**(pos-1)))%(10**pos) # extracts the positional values
    while(num>0):
        for div in ls:

            # CASE 1: Logic for 1, 5 and 10
            if num/div == 1:
                #print("here")
                print(st[div], end="")
                num-=div
                break

            # CASE 2: logic for 2, 3, 6 and 8
            if num/div > 1:
                print(st[div],end="")
                num-=div
                break

            # CASE 3: Logic for 4 and 9
            if (num+(10**(pos-1)))/div == 1:
                print(st[div-num], end="")
                print(st[div], end="")
                num-=div
                break

Output Test

99
XCIX

499
CDXCIX

1954
MCMLIV

1990
MCMXC

2014
MMXIV

35
XXXV

994
CMXCIV
Answered By: lu5er

Here’s a lambda function for integer to roman numeral conversion, working up to 3999. It anchors some corner of the space of “unreadable things you probably don’t actually want to do”. But it may amuse someone:

lambda a: (
    "".join(reversed([
      "".join([
          "IVXLCDM"[int(d)+i*2]
          for d in [
              "", "0", "00", "000", "01",
              "1", "10", "100", "1000", "02"][int(c)]])
          for i,c in enumerate(reversed(str(a))) ]))
     )

This approach gives an alternative to using arithmetical manipulations to
isolate decimal digits and their place, as OP and many of the examples do.
The approach here goes straight for converting the decimal number to a string.
That way, digits can be isolated by list indexing. The data table is fairly
compressed, and no subtraction or division is used.

Admittedly, in the form given, whatever is gained in brevity is immediately
given up in readability. For people without time for puzzles, a version below
is given that avoids list comprehension and lambda functions.

Stepthrough

But I’ll explain the lambda function version here…

Going from back to front:

  1. Convert a decimal integer to a reversed string of its digits, and enumerate
    (i) over the reversed digits (c).

    ....
    for i,c in enumerate(reversed(str(a)))
    ....
    
  2. Convert each digit c back to an integer (range of 0-9), and use it as an index into a list of magic digit strings. The magic is explained a little later on.

    ....
    [ "", "0", "00", "000", "01",
     "1", "10", "100", "1000", "02"][int(c)]])
    ....
    
  3. Convert your selected magic digit string into a string of roman numeral
    “digits”. Basically, you now have your decimal digit expressed as roman
    numeral digits appropriate to the original 10’s place of the decimal digit.
    This is the target of the generate_all_of_numeral function used by the OP.

    ....
    "".join([
        "IVXLCDM"[int(d)+i*2]
        for d in <magic digit string>
    ....
    
  4. Concatenate everything back in reversed order. The reversal is of the order
    of the digits, but order within the digits (“digits”?) is unaffected.

    lambda a: (
        "".join(reversed([
        <roman-numeral converted digits>
        ]))
    

The Magic String List

Now, about that list of magic strings. It allows selecting the appropriate
string of roman numeral digits (up to four of them, each being one of three types 0, 1, or 2) for each different 10’s place that a decimal digit can occupy.

  • 0 -> “”; roman numerals don’t show zeros.
  • 1 -> “0”; 0 + 2*i maps to I, X, C or M -> I, X, C or M.
  • 2 -> “00”; like for 1, x2 -> II, XX, CC, MM.
  • 3 -> “000”; like for 1, x3 -> III, XXX, CCC, MMM.
  • 4 -> “01”; like for 1, then 1 +2*i maps to V, L, or D -> IV, XL, CD.
  • 5 -> “1”; maps to odd roman numeral digits -> V, L, D.
  • 6 -> “10”; reverse of 4 -> VI, LX, DC.
  • 7 -> “100”; add another I/X/C -> VII LXX, DCC
  • 8 -> “1000”; add another I/X/C -> VIII, LXXX, DCCC
  • 9 -> “02”; like for 1, plus the next 10’s level up (2 + i*2) -> IX, XC, CM.

At 4000 and above, this will throw an exception. “MMMM” = 4000, but this
doesn’t match the pattern anymore, breaking the assumptions of the algorithm.

Rewritten version

…as promised above…

def int_to_roman(a):
    all_roman_digits = []
    digit_lookup_table = [
        "", "0", "00", "000", "01",
        "1", "10", "100", "1000", "02"]
    for i,c in enumerate(reversed(str(a))):
        roman_digit = ""
        for d in digit_lookup_table[int(c)]:
          roman_digit += ("IVXLCDM"[int(d)+i*2])
        all_roman_digits.append(roman_digit)
    return "".join(reversed(all_roman_digits))

I again left out exception trapping, but at least now there’s a place to put it inline.

Answered By: d5ous

A KISS version of Manhattan’s algorithm, without any "advanced" notion such as OrderedDict, recursion, generators, inner function and break:

ROMAN = [
    (1000, "M"),
    ( 900, "CM"),
    ( 500, "D"),
    ( 400, "CD"),
    ( 100, "C"),
    (  90, "XC"),
    (  50, "L"),
    (  40, "XL"),
    (  10, "X"),
    (   9, "IX"),
    (   5, "V"),
    (   4, "IV"),
    (   1, "I"),
]

def int_to_roman(number):
    result = ""
    for (arabic, roman) in ROMAN:
        (factor, number) = divmod(number, arabic)
        result += roman * factor
    return result

An early exit could be added as soon as number reaches zero, and the string accumulation could be made more pythonic, but my goal here was to produce the requested basic program.

Tested on all integers from 1 to 100000, which ought to be enough for anybody.

EDIT: the slightly more pythonic and faster version I alluded to:

def int_to_roman(number):
    result = []
    for (arabic, roman) in ROMAN:
        (factor, number) = divmod(number, arabic)
        result.append(roman * factor)
        if number == 0:
            break
    return "".join(result)
Answered By: Aristide
roman_map = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'),
(50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

def IntToRoman (xn):
    x = xn
    y = 0
    Str = ""
    for i, r in roman_map:
         # take the number and divisible by the roman number from 1000 to 1.
        y = x//i    

        for j in range(0, y):
            # If after divisibility is not 0 then take the roman number from list into String.
            Str = Str+r 

        # Take the remainder to next round.
        x = x%i 
    print(Str)
    return Str

Test case:

>>> IntToRoman(3251)
MMMCCLI
'MMMCCLI'
Answered By: tim_hong

I referred to this url for online decimal to roman conversion. If we extend the range of decimals up to 3,999,999 the script given by @Manhattan will not work. Here is the the correct script up to the range of 3,999,999.

def int_to_roman(num):
    _values = [
        1000000, 900000, 500000, 400000, 100000, 90000, 50000, 40000, 10000, 9000, 5000, 4000, 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]

    _strings = [
        'M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]

    result = ""
    decimal = num

    while decimal > 0:
        for i in range(len(_values)):
            if decimal >= _values[i]:
                if _values[i] > 1000:
                    result += u'u0304'.join(list(_strings[i])) + u'u0304'
                else:
                    result += _strings[i]
                decimal -= _values[i]
                break
    return result

The unicode character u’304′ prints the overline char; e.g.
enter image description here

Sample Output:

enter image description here

Answered By: Abhishek Kulkarni

start subtracting 1000,900… to 1 from A and stops when it finds positive.add corresponding roman to ans and make A to A-i where i is (1,4,5,9,10…..) repeat while A does not become 0.

def intToRoman(self, A):
    l=[[1,'I'],[4,'IV'],[5,'V'],[9,'IX'],[10,'X'],[40,'XL'],[50,'L'],
       [90,'XC'],[100,'C'],[400,'CD'],[500,'D'],[900,'CM'],[1000,'M']]
    ans=""
    while(A>0):
        for i,j in l[::-1]:
            if A-i>=0:
                ans+=j
                A=A-i
                break
    return ans
Answered By: himanshu choudhary

This is my recursive function approach to convert a number to its roman equivalent

    def solution(n):
        # TODO convert int to roman string
        string=''
        symbol=['M','D','C','L','X','V','I']
        value = [1000,500,100,50,10,5,1]
        num = 10**(len(str(n))-1)
        quo = n//num
        rem=n%num
        if quo in [0,1,2,3]:
            string=string+symbol[value.index(num)]*quo
        elif quo in [4,5,6,7,8]:
            tem_str=symbol[value.index(num)]+symbol[value.index(num)-1]
                    +symbol[value.index(num)]*3
            string=string+tem_str[(min(quo,5)-4):(max(quo,5)-3)]
        else:
            string=string+symbol[value.index(num)]+symbol[value.index(num)-2]
        if rem==0:
            return string
        else:
            string=string+solution(rem)
        return string

print(solution(499))
print(solution(999))
print(solution(2456))
print(solution(2791))
CDXCIX
CMXCIX
MMCDLVI
MMDCCXCI
Answered By: Ujjwal Kant

I was working through this conversion as a kata exercise, and I came up with a solution that takes advantage of Python’s string operations:

from collections import namedtuple

Abbreviation = namedtuple('Abbreviation', 'long short')
abbreviations = [
    Abbreviation('I' * 1000, 'M'),
    Abbreviation('I' * 500, 'D'),
    Abbreviation('I' * 100, 'C'),
    Abbreviation('I' * 50, 'L'),
    Abbreviation('I' * 10, 'X'),
    Abbreviation('I' * 5, 'V'),
    Abbreviation('DCCCC', 'CM'),
    Abbreviation('CCCC', 'CD'),
    Abbreviation('LXXXX', 'XC'),
    Abbreviation('XXXX', 'XL'),
    Abbreviation('VIIII', 'IX'),
    Abbreviation('IIII', 'IV')
]


def to_roman(arabic):
    roman = 'I' * arabic
    for abbr in abbreviations:
        roman = roman.replace(abbr.long, abbr.short)

    return roman

I like its simplicity! No need for modulo operations, conditionals, or multiple loops. Of course, you don’t need namedtuples either; you can use plain tuples or lists instead.

Answered By: Jorge Aranda

Another way.
I wrote recursive loop by roman symbols, so the max depth of recursion equals length of roman tuple:

ROMAN = ((1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
    (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
    (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I'))

def get_romans(number):
    return do_recursive(number, 0, '')


def do_recursive(number, index, roman):
    while number >= ROMAN[index][0]:
        number -= ROMAN[index][0]
        roman += ROMAN[index][1]
    if number == 0:
        return roman
    return check_recursive(number, index + 1, roman)


if __name__ == '__main__':
    print(get_romans(7))
    print(get_romans(78))
Answered By: VolArt

Write a simple code which takes the number, decreases the number, and appends its corresponding value in Roman numerals in a list and finally converts it in the string. This should work for range 1 to 3999

for no in range(1,3999):
    r_st=list()
    a=no
    while(no>1000):
        r_st.append("M")
        no-=1000
    if(no>899 and no<1000):
        r_st.append("CM")
        no-=900
    if(no>499):
        r_st.append("D")
        no-=500
    if(no>399):
        r_st.append("CD")
        no-=400
    while(no>99):
        r_st.append("C")
        no-=100
    if(no>89):
        r_st.append("LC")
        no-=90
    if(no>50):
        r_st.append("L")
        no-=50
    if(no>39):
        r_st.append("XL")
        no-=40
    while(no>9):
        r_st.append("X")
        no-=10
    if(no>8):
        r_st.append("IX")
        no-=9
    if(no>4):
        r_st.append("V")
        no-=5
    if(no>3):
        r_st.append("IV")
        no-=4
    while(no>0):
        r_st.append("I")
        no-=1
    r_st=''.join(r_st)
    print(a,"==",r_st)
Answered By: Ritik Saraswat

Here is my approach to solving this. The given number is first converted to a string so that then we can easily iterate over every digit to get the Roman part for the corresponding digit. To get the roman part for each digit I have grouped the Roman letters into 1 and 5 for each decimal position so the list of roman characters grouped based on decimal positions would look like [[‘I’, ‘V’], [‘X’, ‘L’], [‘C’, ‘D’], [‘M’]], where characters follow the order or ones, tens, hundreds, and thousands.

So we have digits to loop over and the roman characters for each order of the decimal place, we just need to prepare digits 0-9 using the above character list. The variable “order” picks the correct set of characters based on the decimal position of current digit, this is handled automatically as we are going from highest decimal place to lowest. Following is the full code:

def getRomanNumeral(num):
    # ---------- inner function -------------------
    def makeRomanDigit(digit, order):    
        chars = [['I', 'V'], ['X', 'L'], ['C', 'D'], ['M']]
        if(digit == 1):
            return chars[order][0]
        if(digit == 2):
            return chars[order][0] + chars[order][0]
        if(digit == 3):
            return chars[order][0] + chars[order][0] + chars[order][0]
        if(digit == 4):
            return  chars[order][0] + chars[order][1]
        if(digit == 5):
            return chars[order][1]
        if(digit == 6):
            return chars[order][1] + chars[order][0]
        if(digit == 7):
            return chars[order][1] + chars[order][0] + chars[order][0]
        if(digit == 8):
            return chars[order][1] + chars[order][0] + chars[order][0] + chars[order][0]
        if(digit == 9):
            return chars[order][0] + chars[order+1][0]
        if(digit == 0):
            return ''
    #--------------- main -----------------
    str_num = str(num)
    order = len(str_num) - 1
    result = ''
    for digit in str_num:
        result += makeRomanDigit(int(digit), order)
        order-=1
    return result

A few tests:

getRomanNumeral(112)
'CXII'

getRomanNumeral(345)
'CCCXLV'

getRomanNumeral(591)
'DXCI'

getRomanNumeral(1000)
'M'

I know a lot can be improved in the code or approach towards the problem, but this was my first attempt at this problem.

Answered By: Aditya Shakya

I have produced an answer that works for any int >= 0:

Save the following as romanize.py

def get_roman(input_number: int, overline_code: str = 'u0305') -> str:
    """
    Recursive function which returns roman numeral (string), given input number (int)

    >>> get_roman(0)
    'N'
    >>> get_roman(3999)
    'MMMCMXCIX'
    >>> get_roman(4000)
    'MVu0305'
    >>> get_roman(4000, overline_code='^')
    'MV^'
    """
    if input_number < 0 or not isinstance(input_number, int):
        raise ValueError(f'Only integers, n, within range, n >= 0 are supported.')
    if input_number <= 1000:
        numeral, remainder = core_lookup(input_number=input_number)
    else:
        numeral, remainder = thousand_lookup(input_number=input_number, overline_code=overline_code)
    if remainder != 0:
        numeral += get_roman(input_number=remainder, overline_code=overline_code)
    return numeral


def core_lookup(input_number: int) -> (str, int):
    """
    Returns highest roman numeral (string) which can (or a multiple thereof) be looked up from number map and the
    remainder (int).

    >>> core_lookup(3)
    ('III', 0)
    >>> core_lookup(999)
    ('CM', 99)
    >>> core_lookup(1000)
    ('M', 0)
    """
    if input_number < 0 or input_number > 1000 or not isinstance(input_number, int):
        raise ValueError(f'Only integers, n, within range, 0 <= n <= 1000 are supported.')
    basic_lookup = NUMBER_MAP.get(input_number)
    if basic_lookup:
        numeral = basic_lookup
        remainder = 0
    else:
        multiple = get_multiple(input_number=input_number, multiples=NUMBER_MAP.keys())
        count = input_number // multiple
        remainder = input_number % multiple
        numeral = NUMBER_MAP[multiple] * count
    return numeral, remainder


def thousand_lookup(input_number: int, overline_code: str = 'u0305') -> (str, int):
    """
    Returns highest roman numeral possible, that is a multiple of or a thousand that of which can be looked up from
    number map and the remainder (int).

    >>> thousand_lookup(3000)
    ('MMM', 0)
    >>> thousand_lookup(300001, overline_code='^')
    ('C^C^C^', 1)
    >>> thousand_lookup(30000002, overline_code='^')
    ('X^^X^^X^^', 2)
    """
    if input_number <= 1000 or not isinstance(input_number, int):
        raise ValueError(f'Only integers, n, within range, n > 1000 are supported.')
    num, k, remainder = get_thousand_count(input_number=input_number)
    numeral = get_roman(input_number=num, overline_code=overline_code)
    numeral = add_overlines(base_numeral=numeral, num_overlines=k, overline_code=overline_code)

    # Assume:
    # 4000 -> MV^, https://en.wikipedia.org/wiki/4000_(number)
    # 6000 -> V^M, see https://en.wikipedia.org/wiki/6000_(number)
    # 9000 -> MX^, see https://en.wikipedia.org/wiki/9000_(number)
    numeral = numeral.replace(NUMBER_MAP[1] + overline_code, NUMBER_MAP[1000])
    return numeral, remainder


def get_thousand_count(input_number: int) -> (int, int, int):
    """
    Returns three integers defining the number, number of thousands and remainder

    >>> get_thousand_count(999)
    (999, 0, 0)
    >>> get_thousand_count(1001)
    (1, 1, 1)
    >>> get_thousand_count(2000002)
    (2, 2, 2)
    """
    num = input_number
    k = 0
    while num >= 1000:
        k += 1
        num //= 1000
    remainder = input_number - (num * 1000 ** k)
    return num, k, remainder


def get_multiple(input_number: int, multiples: iter) -> int:
    """
    Given an input number(int) and a list of numbers, finds the number in list closest (rounded down) to input number

    >>> get_multiple(45, [1, 2, 3])
    3
    >>> get_multiple(45, [1, 2, 3, 44, 45, 46])
    45
    >>> get_multiple(45, [1, 4, 5, 9, 10, 40, 50, 90])
    40
    """
    options = sorted(list(multiples) + [input_number])
    return options[options.index(input_number) - int(input_number not in multiples)]


def add_overlines(base_numeral: str, num_overlines: int = 1, overline_code: str = 'u0305') -> str:
    """
    Adds overlines to input base numeral (string) and returns the result.

    >>> add_overlines(base_numeral='II', num_overlines=1, overline_code='^')
    'I^I^'
    >>> add_overlines(base_numeral='I^I^', num_overlines=1, overline_code='^')
    'I^^I^^'
    >>> add_overlines(base_numeral='II', num_overlines=2, overline_code='^')
    'I^^I^^'
    """
    return ''.join([char + overline_code*num_overlines if char.isalnum() else char for char in base_numeral])


def gen_number_map() -> dict:
    """
    Returns base number mapping including combinations like 4 -> IV and 9 -> IX, etc.
    """
    mapping = {
        1000: 'M',
        500: 'D',
        100: 'C',
        50: 'L',
        10: 'X',
        5: 'V',
        1: 'I',
        0: 'N'
    }
    for exponent in range(3):
        for num in (4, 9,):
            power = 10 ** exponent
            mapping[num * power] = mapping[1 * power] + mapping[(num + 1) * power]
    return mapping


NUMBER_MAP = gen_number_map()


if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=True, raise_on_error=True)
    # Optional extra tests
    # doctest.testfile('test_romanize.txt', verbose=True)

Here are some extra tests in case useful.
Save the following as test_romanize.txt in the same directory as the romanize.py:

The ``romanize`` module
=======================


The ``get_roman`` function
--------------------------

Import statement:

    >>> from romanize import get_roman

Tests:

    >>> get_roman(0)
    'N'
    >>> get_roman(6)
    'VI'
    >>> get_roman(11)
    'XI'
    >>> get_roman(345)
    'CCCXLV'
    >>> get_roman(989)
    'CMLXXXIX'
    >>> get_roman(989000000, overline_code='^')
    'C^^M^^L^^X^^X^^X^^M^X^^'
    >>> get_roman(1000)
    'M'
    >>> get_roman(1001)
    'MI'
    >>> get_roman(2000)
    'MM'
    >>> get_roman(2001)
    'MMI'
    >>> get_roman(900)
    'CM'
    >>> get_roman(4000, overline_code='^')
    'MV^'
    >>> get_roman(6000, overline_code='^')
    'V^M'
    >>> get_roman(9000, overline_code='^')
    'MX^'
    >>> get_roman(6001, overline_code='^')
    'V^MI'
    >>> get_roman(9013, overline_code='^')
    'MX^XIII'
    >>> get_roman(70000000000, overline_code='^')
    'L^^^X^^^X^^^'
    >>> get_roman(9000013, overline_code='^')
    'M^X^^XIII'
    >>> get_roman(989888003, overline_code='^')
    'C^^M^^L^^X^^X^^X^^M^X^^D^C^C^C^L^X^X^X^V^MMMIII'


The ``get_thousand_count`` function
--------------------------

Import statement:

    >>> from romanize import get_thousand_count

Tests:

    >>> get_thousand_count(13)
    (13, 0, 0)
    >>> get_thousand_count(6013)
    (6, 1, 13)
    >>> get_thousand_count(60013)
    (60, 1, 13)
    >>> get_thousand_count(600013)
    (600, 1, 13)
    >>> get_thousand_count(6000013)
    (6, 2, 13)
    >>> get_thousand_count(999000000000000000000000000999)
    (999, 9, 999)
    >>> get_thousand_count(2005)
    (2, 1, 5)
    >>> get_thousand_count(2147483647)
    (2, 3, 147483647)


The ``core_lookup`` function
--------------------------

Import statement:

    >>> from romanize import core_lookup

Tests:

    >>> core_lookup(2)
    ('II', 0)
    >>> core_lookup(6)
    ('V', 1)
    >>> core_lookup(7)
    ('V', 2)
    >>> core_lookup(19)
    ('X', 9)
    >>> core_lookup(900)
    ('CM', 0)
    >>> core_lookup(999)
    ('CM', 99)
    >>> core_lookup(1000)
    ('M', 0)
    >>> core_lookup(1000.2)
    Traceback (most recent call last):
    ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.
    >>> core_lookup(10001)
    Traceback (most recent call last):
    ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.
    >>> core_lookup(-1)
    Traceback (most recent call last):
    ValueError: Only integers, n, within range, 0 <= n <= 1000 are supported.


The ``gen_number_map`` function
--------------------------

Import statement:

    >>> from romanize import gen_number_map

Tests:

    >>> gen_number_map()
    {1000: 'M', 500: 'D', 100: 'C', 50: 'L', 10: 'X', 5: 'V', 1: 'I', 0: 'N', 4: 'IV', 9: 'IX', 40: 'XL', 90: 'XC', 400: 'CD', 900: 'CM'}


The ``get_multiple`` function
--------------------------

Import statement:

    >>> from romanize import get_multiple
    >>> multiples = [0, 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000]

Tests:

    >>> get_multiple(0, multiples)
    0
    >>> get_multiple(1, multiples)
    1
    >>> get_multiple(2, multiples)
    1
    >>> get_multiple(3, multiples)
    1
    >>> get_multiple(4, multiples)
    4
    >>> get_multiple(5, multiples)
    5
    >>> get_multiple(6, multiples)
    5
    >>> get_multiple(9, multiples)
    9
    >>> get_multiple(13, multiples)
    10
    >>> get_multiple(401, multiples)
    400
    >>> get_multiple(399, multiples)
    100
    >>> get_multiple(100, multiples)
    100
    >>> get_multiple(99, multiples)
    90


The ``add_overlines`` function
--------------------------

Import statement:

    >>> from romanize import add_overlines

Tests:

    >>> add_overlines('AB')
    'Au0305Bu0305'
    >>> add_overlines('Au0305Bu0305')
    'Au0305u0305Bu0305u0305'

    >>> add_overlines('AB', num_overlines=3, overline_code='^')
    'A^^^B^^^'
    >>> add_overlines('A^B^', num_overlines=1, overline_code='^')
    'A^^B^^'

    >>> add_overlines('AB', num_overlines=3, overline_code='u0305')
    'Au0305u0305u0305Bu0305u0305u0305'
    >>> add_overlines('Au0305Bu0305', num_overlines=1, overline_code='u0305')
    'Au0305u0305Bu0305u0305'

    >>> add_overlines('A^B', num_overlines=3, overline_code='^')
    'A^^^^B^^^'

    >>> add_overlines('A^B', num_overlines=0, overline_code='^')
    'A^B'
Answered By: dnk8n

The code for this roman numeral does not check for errors like wrong letters it is just for a perfect roman numeral letters

roman_dict = {'M':1000, 'CM':900, 'D':500, 'CD':400, 'C':100, 'XC':90,
         'L':50, 'XL':40, 'X':10, 'IX':9, 'V':5, 'IV':4,'I':1}

roman = input('Enter the roman numeral: ').upper()
roman_initial = roman # used to retain the original roman figure entered

lst = []


while roman != '':    
if len(roman) > 1:
    check = roman[0] + roman[1]
    if check in roman_dict and len(roman) > 1:
        lst.append(check)
        roman = roman[roman.index(check[1])+1:]
    else:
        if check not in roman_dict and len(roman) > 1:
            lst.append(check[0])
            roman = roman[roman.index(check[0])+1:]   
else:
    if len(roman)==1:
        check = roman[0]
        lst.append(check[0])
        roman = ''

if lst != []:
Sum = 0
for i in lst:
    if i in roman_dict:
        Sum += roman_dict[i]
print('The roman numeral %s entered is'%(roman_initial),Sum)

Interesting question. Several approaches but haven’t seen this one yet. We can trade execution time for memory, and reduce potential for pesky arithmetic errors (off-by-one, int vs float div, etc).

Each arabic digit (1s, 10s, 100s, etc) translates to a unique Roman sequence. So just use a lookup table.

ROMAN = {
    0 : ['', 'm', 'mm', 'mmm'],
    1 : ['', 'c', 'cc', 'ccc', 'cd', 'd', 'dc', 'dcc', 'dccc', 'cm'],
    2 : ['', 'x', 'xx', 'xxx', 'xl', 'l', 'lx', 'lxx', 'lxxx', 'xc'],
    3 : ['', 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'ix'],
}

def to_roman (num, lower = True):
    '''Return the roman numeral version of num'''
    ret = ''
    digits = '%04d' % num
    for pos, digit in enumerate (digits):
        ret += ROMAN [pos] [int (digit)]
    return lower and ret or ret.upper ()

You can add checks for 0 > num > 4000, but not necessary as lookup will fail on int conversion for ‘-‘ or index out of range. I prefer lowercase, but upper available as well.

Digit selection could be done arithmetically, but algorithm becomes a bit trickier. Lookups are simple and effective.

Answered By: Ed_

Here is a simpler way, i followed the basic conversion method explained here

Please find the code below:

input = int(raw_input()) # enter your integerval from keyboard
Decimals =[1,4,5,9,10,40,50,90,100,400,500,900,1000]    
Romans =['I','IV','V','IX','X','XL','L','XC','C','CD','D','CM','M']
romanletters= [] # empty array to fill each corresponding roman letter from the Romans array
while input != 0: 
    # we use basic formula of converstion, therefore input is substracted from 
    # least maximum similar number from Decimals array until input reaches zero 
    for val in range (len(Decimals)):
        if input >= Decimals[val]:
            decimal = Decimals[val]
            roman = Romans[val]
    difference = input - decimal
    romanletters.append(roman)
    input = difference
dec_to_roman = ''.join(romanletters) # concatinate the values
print dec_to_roman
Answered By: Jovel

I think this is the simplest approach. Roman Numerals have a range 1 to 3999.

def toRomanNumeral(n):
  NumeralMatrix = [
      ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
      ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
      ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
      ["", "M", "MM", "MMM"]
  ]
  # The above matrix helps us to write individual digits of the input as roman numeral.
  # Rows corresponds to the place of the digit (ones, tens, hundreds, etc).
  # Column corresponds to the digit itself.
  
  rn = ""
  d = []
  # d is an array to store the individual digits of the input 

  while (n!=0):
      d.append(n%10)
      n =int(n/10)
  
  for i in range(len(d), 0, -1):
      rn += NumeralMatrix[i-1][d[i-1]]
      # [i-1] is the digit's place (0 - ones, 1 - tens, etc)
      # [d[i-1]] is the digit itself

  return rn

print(toRomanNumeral(49))
# XLIX
Answered By: Zohaib Hamdule

Here’s a short, recursive solution:

romVL = [999, 'IM', 995, 'VM', 990, 'XM', 950, 'LM', 900, 'CM', 500, 'D', 499, 'ID', 495, 'VD', 490, 'XD', 450, 'LD', 400, 'CD', 100, 'C', 99, 'IC', 95, 'VC', 90, 'XC', 50, 'L', 49, 'IL', 45, 'VL', 40, 'XL', 10, 'X', 9, 'IX', 5, 'V', 4, 'IV', 1, 'I']

def int2rom(N,V=1000,L="M",*rest):
    return N//V*L + int2rom(N%V,*rest or romVL) if N else ""

Examples:

int2rom(1999) 'MIM'
int2rom(1938) 'MCMXXXVIII'
int2rom(1988) 'MLMXXXVIII'
int2rom(2021) 'MMXXI'

and the reverse function:

def rom2int(R):
    LV = {"M":1000,"D":500,"C":100,"L":50,"X":10,"V":5,"I":1}
    return sum(LV[L]*[1,-1][LV[L]<LV[N]] for L,N in zip(R,R[1:]+"I"))
Answered By: Alain T.

I grabbed this from my GitHub (you can find a more detailed version there). This function has a fixed computation time and makes use of no external libraries. It works for all integers between 0 and 1000.

def to_roman(n):
    try:
    if n >= 0 and n <= 1000:
        d = [{'0':'','1':'M'},
             {'0':'','1':'C','2':'CC','3':'CCC','4':'DC','5':'D',
              '6':'DC','7':'DCC','8':'DCCC','9':'MC'},
             {'0':'','1':'X','2':'XX','3':'XXX','4':'XL','5':'L',
              '6':'LX','7':'LXX','8':'LXXX','9':'CX'},
             {'0':'','1':'I','2':'II','3':'III','4':'IV','5':'V',
              '6':'VI','7':'VII','8':'VIII','9':'IX'}]
        x = str('0000' + str(n))[-4:]
        r = ''
        for i in range(4):
        r = r + d[i][x[i]]
        return r
    else:
        return '`n` is out of bounds.'
    except:
        print('Is this real life?nIs `n` even an integer?')

Output from entering n=265:

>>> to_roman(265)
    'CCLXV'
Answered By: Arturo Sbr
def convert_to_roman(number, rom_denom, rom_val):
    '''Recursive solution'''
    #Base case
    if number == 0:
        return ''
    else:
        rom_str = (rom_denom[0] * (number//rom_val[0])) + convert_to_roman(number % 
        rom_val[0], rom_denom[1:], rom_val[1:]) #Recursive call
    return rom_str

rom_denom = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I']
rom_val = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
number = int(input("Enter numeral to convert: "))
rom_str = convert_to_roman(number, rom_denom, rom_val)
print(rom_str)
Answered By: John Smith

The Python package roman (repository) can be used to convert to and from roman numerals:

import roman

r = roman.toRoman(5)
assert r == 'V', r
n = roman.fromRoman('V')
assert n == 5, n

This package can be installed from the Python Package Index (PyPI) using the package manager pip:

pip install roman
Answered By: 0 _
def convert_to_roman(num):
    # print(num)
    roman=""
    while(num!=0):
        if num in range(1000,5000):
            roman+="M"*(num//1000)
            num-=(num//1000)*1000

        if num in range(900,1000):          #range(a,b) works from a to b-1 here from 900->999
            roman+="CM"
            num-=900

        if num in range(500,900):
            roman+="D"
            num-=500

        if num in range(400,500):
            roman+="CD"
            num-=400

        if num in range(100,400):
            roman+="C"*(num//100)
            num-=100*(num//100)

        if num in range(90,100):
            roman+="XC"
            num-=90

        if num in range(50,90):
            roman+="L"
            num-=50

        if num in range(40,50):
            roman+="XL"
            num-=40

        if num in range(10,40):
            roman+="X"*(num//10)
            num-=10*(num//10)

        if num==9:
            roman+="IX"
            num-=9

        if num in range(5,9):
            roman+="V"
            num-=5

        if num ==4:
            roman+="IV"
            num-=4

        if num ==3:
            roman+="III"
            num-=3

        if num ==2:
            roman+="II"
            num-=2

        if num ==1:
            roman+="I"
            num-=1


    # print(num)    
    return roman
    #Start writing your code here
num=888
print(num,":",convert_to_roman(num))
Answered By: Tushar Pangare

Here’s what I tried:

def int_to_roman(num):
    dict_of_known_val = {1000: 'M', 900: 'CM', 500: 'D', 400: 'CD', 100: 'C',
                         90: 'XC', 50: 'L', 40: 'XL', 10: 'X', 9: 'IX', 5: 'V', 4: 'IV', 1: 'I'}
    result = ''
    for key, value in dict_of_known_val.items():
        x, y = divmod(num, key)
        result += value * x
        num = y
    return result

This code works for me.

Answered By: vivek kumar

A simple string concatenation through iteration:

def roman(x: int) -> str:
    """Convert into to roman numeral"""
    # Iterative
    L = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'),
         (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'),
         (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]

    if x >= 1:
        y = ""
        for val, sym in L:
            y += sym*(x//val)
            x -= val*(x//val)
    else:
        return None
    return y
>>> roman(399)
'CCCXCIX'
Answered By: Freddy Mcloughlan
class Solution:
    def intToRoman(self, num: int) -> str:
        if num>3999:

            return
        value = [1000,900,500,400,100,90,50,40,10,9,5,4,1]
        sym = ["M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"]
        index = 0
        result = ""
        while num>0:
            res = num//value[index]
            num = num%value[index]
            while res>0:
                result = result+sym[index]
                res =res-1

            index+=1
        return  result
if __name__ == '__main__':
    obj = Solution()
    print(obj.intToRoman(1994))
Answered By: Kartik Verma

After many attempts, I came out with a solution that I find very compact and understandable to create the first 4000 roman numerals:

def toRoman(n):
    g = {
        1: ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
        2: ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "LC"],
        3: ["", "C", "CC", "CCC", "CD", "DC", "DCC", "DCCC", "CM"],
        4: ["", "M", "MM", "MMM", "MMMM"],
    }
    return "".join(g[len(str(n)) - ind][int(s)] for ind, s in enumerate(str(n)))
Answered By: G M

Here’s how I did it (works for 1-3999; however, it can be extended as needed).

def intToRoman(num: int) -> str:
    nums = {0: '', 1: 'I', 2: 'II', 3: 'III', 4: 'IV', 5: 'V', 6: 'VI', 7: 'VII', 8: 'VIII',
    9: 'IX', 10: 'X', 20: 'XX', 30: 'XXX', 40: 'XL', 50: 'L',
    60: 'LX', 70: 'LXX', 80: 'LXXX', 90: 'XC', 100: 'C', 200: 'CC', 300: 'CCC', 400: 'CD', 
    500: 'D', 600: 'DC', 700:'DCC', 800: 'DCCC', 900: 'CM', 1000: 'M', 2000: 'MM', 3000: 'MMM'}

    numerals = []
    digits = [int(x) for x in reversed(str(num))]
    times_ten = [10**i for i in range(len(digits))]

    for times, digit in zip(times_ten, digits):
        val = digit*times
        numerals.append(nums.get(val))
    return ''.join(x for x in reversed(numerals))

It starts off with a list of the roman numerals from 1-9, then 10-90 (counting in 10s), 100-900 (counting in 100s), etc. It then sets digits as the reversed order of the input number, and creates a list times_ten which has all the powers of ten from 100 to 10len(digits)-1.

Then it iterates over both of them via the zip built-in function, and sets a variable val as the product of the 2. Then it adds to numerals (which is the list with the roman numerals in it) the item in the dictionary for the key ‘val’. For example, if the digit is 4 and it is in the tens place, val=4*10=40. nums.get(40)=’XL’, so ‘XL’ would be appended.

Finally, it returns the numeral by joining the numerals list in reverse.

Answered By: Jason Grace
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.