Let Python do the work for you and figure out the roman numerals for a given integer. I have to ask you to keep the integer values somewhat reasonably low (from 1 to 4999), since roman numerals from 5000 on use characters with an overline and most PCs don't have those in the character set.

2,216 Views
``````# convert an integer to a roman numeral
# keep it reasonable since from 5000 on special characters are used
# tested with Python24       vegaseat        25jan2007

def int2roman(number):
numerals = { 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" }
result = ""
for value, numeral in sorted(numerals.items(), reverse=True):
while number >= value:
result += numeral
number -= value
return result

print int2roman(input("Enter an integer (1 to 4999): "))

"""
Enter an integer (1 to 4999): 2007
MMVII
"""``````

Scientist

i'm just playing around with python and decided to try this code out but keep getting a syntax error pointing to the colon after the 1 in,

I just tested it with python 2.6 and it works. For python 3.1, I had to change the last statement to

``print(int2roman(int(input("Enter an integer (1 to 4999): "))))``

and it works.

@pythonuser18
you used () instead of {}
a dictionary container needs the curly braces.

``````def DecToRom (number) :
numerals={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"}
result=""
for value, numeral in sorted(numerals.items(), reverse=True):
while number >= value:
result += numeral
number -= value
return result
print DecToRom(raw_input(“Decimal number: “))
``````

could someone tell me why this isn't working? It says Syntax Error: invalid syntax

I know the indents aren't formatted correctly on this post, but they are as they are suppose to be in python

@@pythonuser18 For reference, I got it working, with python 2.6 and this last line:

``print DecToRom(int(raw_input("Decimal number: ")))``
pythonuser18 commented: Thanks a million! +0

Roman to integer. Note that it will take something like XXIXV and convert it. If someone already has a routine to check for valid input, please post it. And I'm afraid we've just eliminated one standard homework question. Oh well, nothing lasts forever.

``````roman_to_decimal = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, \
'D': 500, 'M': 1000 }

roman = raw_input("Enter the roman numeral to convert to arabic: ").upper()

converted = True
arabic = 0
for n in range(0, len(roman)-1):
this_char = roman[n]
next_char = roman[n+1]
if (this_char in roman_to_decimal) and \
(next_char in roman_to_decimal):

this_number = roman_to_decimal[this_char]
next_number =  roman_to_decimal[next_char]
print "converting %s to %d....." % (this_char, this_number),
if this_number < next_number:
arabic -= this_number
else:
arabic += this_number
print "Total now =", arabic

else:
print "\nthis chr (%s) or next chr (%s) is not a valid roman numeral" \
% (this_char, next_char)
converted = False
break

if converted:
arabic += roman_to_decimal[roman[len(roman)-1]]

print "\nThe roman numeral", roman, "is equal to",arabic``````

A quick solution that does both directions:

``````# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

mapping = [ ('cd','cccc'), ('xl','xxxx'),('iv','iiii'),('d','ccccc'),('l','xxxxx'),('v','iiiii'), ('cm','ccccccccc'), ('xc','xxxxxxxxx'),('ix','iiiiiiiii')]
mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
for (kort, lang) in mapping: x= x.replace(kort, lang)
x = '+'.join(list(x))
for (karakter, waarde) in bignums: x = x.replace(karakter, str(waarde))
if x=='': x = '0'
return eval(x)

def toroman(x):
val = ''
for (karakter, waarde) in bignums:
val = val + (x / waarde) * karakter
x = x % waarde
for (kort, lang) in mapping:
val = val.replace(lang,kort)
return val``````

Nice concept but fails in execution:

``````# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

# bug testing, translation of variables and reformating
# Tony Veijalainen 2010-06-16

mapping = [ ('cd','cccc'),
('xl','xxxx'),
('iv','iiii'),
('d','ccccc'),
('l','xxxxx'),
('v','iiiii'),
('cm','ccccccccc'),
('xc','xxxxxxxxx'),
('ix','iiiiiiiii')]

mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
for (shortv, longv) in mapping: x= x.replace(shortv, longv)
x = '+'.join(list(x))
for (character, word) in bignums: x = x.replace(character, str(word))
if x=='': x = '0'
return eval(x)

def toroman(x):
val = ''
for (character, word) in bignums:
val = val + (x / word) * character
x = x % word
for (shortv, longv) in mapping:
val = val.replace(longv,shortv)
return val

for i in range(5000):
if fromroman(toroman(i)) != i:
print ('Bug found: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))``````

The code gives plenty of bugs printed.

Got it passing my test by rearranging the values that were present in bug cases in the mapping (cleaned up multiletter expressions by *):

``````# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

# bug testing, translation of variables and reformating
# Tony Veijalainen 2010-06-16

mapping = [ ('d',5*'c'),
('l',5*'x'),
('v',5*'i'),
('cm',9*'c'),
('xc',9*'x'),
('ix',9*'i'),
('cd',4*'c'),
('iv',4*'i'),
('xl',4*'x')]

mapping.reverse()
bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

def fromroman(x):
for (shortv, longv) in mapping: x= x.replace(shortv, longv)
x = '+'.join(list(x))
for (character, word) in bignums: x = x.replace(character, str(word))
if x=='': x = '0'
return eval(x)

def toroman(x):
val = ''
for (character, word) in bignums:
val = val + (x / word) * character
x = x % word
for (shortv, longv) in mapping:
val = val.replace(longv,shortv)
return val

bugs=0
for i in range(5000):
if fromroman(toroman(i)) != i:
print ('Bug found: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))
bugs+=1

print(('Number of bugs found: %i' % bugs) if bugs else 'Test passed!')

""" Output:
Test passed!
"""``````
vegaseat commented: sharp mind +11

Correct fix is take out permanent reverse and use reversed() in to roman translation:

``````# Roman Numerals
# 2010-06-15, Eljakim Schrijvers

mapping = [ ('cd',4*'c'),
('xl',4*'x'),
('iv',4*'i'),
('d',5*'c'),
('l',5*'x'),
('v',5*'i'),
('cm',9*'c'),
('xc',9*'x'),
('ix',9*'i')]

bignums = [ ('m',1000), ('c',100), ('x', 10), ('i',1) ]

## vegaseat function for error check
def int2roman(number):
numerals = { 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" }
result = ""
for value, numeral in sorted(numerals.items(), reverse=True):
while number >= value:
result += numeral
number -= value
return result

def fromroman(x):
for (shortv, longv) in mapping: x= x.replace(shortv, longv) ## reverse order needed
x = '+'.join(list(x))
for (character, word) in bignums: x = x.replace(character, str(word))
if x=='': x = '0'
return eval(x)

def toroman(x):
val = ''
for (character, word) in bignums:
val = val + (x / word) * character
x = x % word
for (shortv, longv) in reversed(mapping): ## reverse here not permanantly
val = val.replace(longv,shortv)
return val

bugs1 = bugs2 = 0
for i in range(5000):
if fromroman(toroman(i)) != i:
print ('Reverse failure: %i, %s, %s' % (i,toroman(i),fromroman(toroman(i))))
bugs1+=1

if  int2roman(i).lower() != toroman(i):
print ('Wrong roman: %i, %s, %s' % (i,int2roman(i),toroman(i)))
bugs2+=1

print(('Number of bugs found: %i reverse failure, %i wrong roman' % (bugs1,bugs2) if bugs1 + bugs2 else 'Test passed!'))
""" Last ilne of output:
Test passed!
"""``````

I am quite embarrassed at the low quality I produced in the middle of the night.

Thank you for fixing it.

Eljakim