BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Algorithms and Data Structures
.NET 1.1+

Convert Roman Numerals into Numbers

In an earlier article we converted integer values into Roman numerals, an ancient numbering system that uses letters to represent values. In this article we will reverse the process, allowing Roman numerals to be evaluated as an integer.

Rule 7

The first rule to added to the class is rule 7. This states that if the entire Roman numeral string contains the letter 'N' then the returned value will be zero. The comparison could be made using the string comparison methods to ensure case-insensitivity. However, as later in the algorithm it will be useful to have an upper case string, we will capitalise the string before testing for 'N'. We will also trim off any excess spaces to reduce the risk of error. These actions can be achieved by adding the following code to the RomanToNumber method:

// Rule 7
roman = roman.ToUpper().Trim();
if (roman == "N") return 0;

Rule 4

Rule 4 states that the letters V, L and D may only appear once in the entire Roman numeral string. A neat way to test for duplicates is to use the Split method to convert the Roman numeral string into an array of items delimited by the numeral character. If there is more than a single instance of the letter, there will be more than two elements in the array. This is tested in an if statement for each letter. If any of the three numerals are repeated then an exception is thrown.

To add rule 4, add the following code to the end of the RomanToNumber method:

// Rule 4
if (roman.Split('V').Length > 2 || roman.Split('L').Length > 2
    || roman.Split('D').Length > 2)
    throw new ArgumentException("Rule 4");

Invalid Numerals and Rule 1

The next section of code performs two checks. Firstly the individual letters are checked to ensure that each is a valid numeral. Secondly, rule 1, which states that a numeral may not be repeated consecutively more than three times, is validated.

This is achieved by looping through the string using a foreach loop to extract each character in turn. The test for invalid characters uses the IndexOf method to determine if the character is within a string of allowed numerals and an exception is thrown if it is not. To check for compliance with rule 1 a counter is incremented every time a letter matches the previous character. If the counter reaches four then too many repetitions exists and an exception is thrown. If the two numerals differ, the counter is reset.

To add the invalid numeral test and the rule 1 compliance check, add the following code to the end of the method:

// Rule 1
int count = 1;
char last = 'Z';
foreach (char numeral in roman)
{
    // Valid character?
    if ("IVXLCDM".IndexOf(numeral) == -1)
        throw new ArgumentException("Invalid numeral");
    
    // Duplicate?
    if (numeral == last)
    {
        count++;
        if (count == 4) throw new ArgumentException("Rule 1");
    }
    else
    {
        count = 1;
        last = numeral;
    }
}

NB: The last variable is initialised with a 'Z' as a dummy value as this cannot match the first numeral causing incorrect results.

22 January 2008