This week while I was solving a Project Euler problem, I came up with a simple roman to decimals converter. I will show its implementation in Python in this post.

## Roman numerals

Romans represented numbers using numerals as follows:

I - 1 V - 5 X - 10 L - 50 C - 100 D - 500 M - 1000

We will consider only three rules to convert them to decimal numbers.

- Numerals must be written in decreasing order.

For example,*MD*is a valid representation of 1500 while*DM*isn’t. - The total value is obtained by adding each successive decreasing numeral to the right.

For example,*VIII*represents 8 (5 + 1 + 1 + 1). See the numerals value decrease from right to left. - As an exception to rule 1., it’s possible to decrease
*I, X*and*C*from the two next numerals with greater values. To do it, we write the lower numeral left of the greater one.

For example, we can decrease*X*from both*L*and*C*:*XL*= 40 (50 – 10) and*XC*= 90 (100 – 10)

However, we can’t subtract*X*from other greater numerals:*X*M = 990 (1000 – 10), isn’t a valid roman numeral.

## A roman to decimal converter

For our converter, we will take advantage that roman numerals are written in decreasing order by analyzing it **starting from the end**. Then we will add the corresponding decimal value of each numeral using a Python dictionary.

We will consider the subtraction of numerals, such as *I *in *IV*, by the fact that the left hand side numeral is lower than the right hand side one (*I < V*). In this case, *I *in *IV* will be parsed as -1 instead of +1.

The dictionary used to convert roman numerals do decimals:

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

See that `roman_dict['D']`

will return `500`

and so on.

The parsing will be implemented using function `decimal`

:

def decimal(roman): """ roman: a string or roman numerals. Returns the equivalent in decimal numbers (int). """ global roman_dict # Analyze string backwards roman_back = list(reversed(list(roman))) value = 0 # To keep track of order right_val = roman_dict[roman_back[0]] for numeral in roman_back: left_val = roman_dict[numeral] # Check for subtraction if left_val < right_val: value -= left_val else: value += left_val right_val = left_val return value

As it was stated before, all we are doing is getting the decimal value of each numeral:

left_val = roman_dict[numeral]

And then verifying if we have to add or subtract the value of that numeral by checking if the left value is lower than the right one:

if left_val < right_val: ...

Let’s check it works with a rather complicated roman numeral:

>>> decimal('MCDXLIX') 1449

It works!

Finally, we have to remark that we’re assuming that the roman numerals are written correctly. This converter will retun a value for any possible combination of roman numerals, even invalid ones such as *IXM*.