Convert Roman Number to Integer in Java

Convert Roman number to Integer in java

1. Introduction

In this article, we look into an interesting problem: How to convert Roman Number to Integer in Java.

Roman numerals are represented by seven different symbols : I, V, X, L, C, D, M. The Integral values associated with each symbol is shown in the table below:

Roman Symbol Value
I1
V5
X10
L50
C100
D500
M1000

Usually, roman numbers are written from left to right, which makes it easier for us to scan each roman character and add the corresponding value for each character to get the result.

For Example: Roman Number III has Integral value is 3 adding value of three I’s together (1+1+1=3).

Similarly for Roman Number: DCLXVI , Its integer value is : 500 + 100 + 50 + 10 +5 + 1= 666.

However, the Roman Number for 4 and 9 are not written as IIII and VIIII, respectively. They are written as IV which is (5-1 = 4), and for 9 it is IX (10 -1=9). This case is for letter I. There are 2 more cases to consider:

  • X can be placed before L (50) and C (100), like XL and XC to make 40 and 90 respectively.
  • Similarly, C can be placed before D and M, like CD and CM to make 400 and 900, respectively. 

Hence, for Roman Number ‘CDXLIX’ the integer is 449.

Note: If a Roman Symbol having smaller value precedes a Symbol with Higher Value, we need to subtract the higher value from the smaller value to get the result. Roman Numbers can have maximum Integral value: 3999 represented as : MMMCMXCIX.

We will implement conversion in two parts:

  • Validate the given Roman number.
  • If Roman number is in correct format, convert it into integer.

2. Validate Roman number using regex

We need to put some validation logic to ensure that input String is a valid roman numeral. One of the approaches to validate it using regular expression.

Here is regular expression which we can use to validate:

^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$

This regular expression matches a string that starts with zero or more M’s, followed by either CM, CD, or D followed by zero to three C’s, followed by either XC, XL, or L followed by zero to three X’s, followed by either IX, IV, or V followed by zero to three I’s, and ends with the end of the string. This covers all the possible combinations of Roman numerals from 1 to 3999.

We can use matches() method of String class to check if input string matches the regular expression. If it doesn’t match we can throw an exception.

// Define the regular expression for valid Roman numerals
   String regex = "^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";

   // Check if the input string matches the regular expression
   if (!roman.matches(regex)) {
      // Throw an exception or return an error message
      throw new IllegalArgumentException("Invalid Roman numeral: " + roman);
   }

3. Using Java 8 Stream

To convert roman number to Integer

  • Create a map with Roman Symbol as key and its corresponding value as value.
  • Declare a variable named result and assign it to zero. This variable will store the final result of the conversion.
  • Create a Stream using IntStream.range() to iterate over characters of Input String.
  • Compare current and next characters such that:
    • If the current character is smaller than the next character, it means that the current character should be subtracted from the result. For example, in XLVII, the X is smaller than the L, so it should be subtracted from the result.
    • Otherwise, if the current character is equal to or larger than the next character, it means that the current character should be added to the result. For example, in XLVII, the L is equal to the L, so it should be added to the result.
package org.arpit.java2blog.generic;

import java.util.HashMap;
import java.util.Map;
import java.util.stream.IntStream;

class RomanToInteger
{

    public static int romanToInteger(String roman)
    {
        // Define the regular expression for valid Roman numerals
        String regex = "^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";

        // Check if the input string matches the regular expression
        if (!roman.matches(regex)) {
            // Throw an exception or return an error message
            throw new IllegalArgumentException("Invalid Roman numeral: " + roman);
        }

        Map<Character,Integer> numbersMap = new HashMap<>();
        numbersMap.put('I',1);
        numbersMap.put('V',5);
        numbersMap.put('X',10);
        numbersMap.put('L',50);
        numbersMap.put('C',100);
        numbersMap.put('D',500);
        numbersMap.put('M',1000);

        // local variable
        final int[] result = {0};

        // A stream to iterate over the characters of the string
        IntStream.range(0, roman.length()).forEach(i -> {
            // Get the current and next character
            char c = roman.charAt(i);
            char next = i < roman.length() - 1 ? roman.charAt(i + 1) : ' ';

            // If the current character is smaller than the next, subtract its value
            if (numbersMap.get(c) < numbersMap.getOrDefault(next, 0)) {
                result[0] -= numbersMap.get(c);
            }
            // Otherwise, add its value
            else {
                result[0] += numbersMap.get(c);
            }
        });

        // Return the result
        return result[0];
    }

    public static void main(String args[])
    {
        // we take input as a String
        String romanNumber="MCMXCIV";
        int result = romanToInteger(romanNumber);

        System.out.println("The Roman Number is: "+romanNumber);
        System.out.println("Its Integer Value is: "+result);

        System.out.println();

        romanNumber="DCCXCIX";
        result = romanToInteger(romanNumber);

        System.out.println("The Roman Number is: "+romanNumber);
        System.out.println("Its Integer Value is: "+result);
    }

}

4. Using Traditional if else and for Loop

Here is logic to for converting Roman number to Integer.

  • We will take a HashMap and for each Roman Character, we will put its respective value in the Map as shown in the table above. The Key would be the Roman Symbol and the Value will be the Integral Value of the Symbol.
  • We iterate through each character in the given Number ,For each character we need to consider two cases :
    • Case 1 : If the Character’s value is greater than the previous character value i.e. The condition is : if (Value(charAt(i)) >Value(charAt(i-1)), we need to perform subtraction as : Value(charAt(i)) - 2* Value(charAt(i-1)) ; then add the result to our answer.
    • Case 2: If the Character’s value is lesser than previous one we simply add its corresponding value to our answer and continue the process.
  • In Case 1, we subtract twice the previous character value because we might have already added the value while processing it, so we subtract twice the value.

Now let us have a quick look at the code in Java:

import java.util.*;

class RomanToInteger
{

 public static int romanToInteger(String roman) 
 {
   // Define the regular expression for valid Roman numerals
   String regex = "^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$";

   // Check if the input string matches the regular expression
   if (!roman.matches(regex)) {
      // Throw an exception or return an error message
      throw new IllegalArgumentException("Invalid Roman numeral: " + roman);
   }

    Map<Character,Integer> numbersMap = new HashMap<>();
    numbersMap.put('I',1);
    numbersMap.put('V',5);
    numbersMap.put('X',10);
    numbersMap.put('L',50);
    numbersMap.put('C',100);   
    numbersMap.put('D',500);   
    numbersMap.put('M',1000);  

    int result=0;

    for(int i=0;i<roman.length();i++)
    {
      char ch = roman.charAt(i);      // Current Roman Character

      //Case 1
      if(i>0 && numbersMap.get(ch) > numbersMap.get(roman.charAt(i-1)))
      {
        result += numbersMap.get(ch) - 2*numbersMap.get(roman.charAt(i-1));
      }

      // Case 2: just add the corresponding number to result.
      else
        result += numbersMap.get(ch);
    }

    return result;
 }

 public static void main(String args[])
 {
   // we take input as a String
   String romanNumber="MCMXCIV";
   int result = romanToInteger(romanNumber);

   System.out.println("The Roman Number is: "+romanNumber);
   System.out.println("Its Integer Value is: "+result);

   System.out.println();

   romanNumber="DCCXCIX";
   result = romanToInteger(romanNumber);

   System.out.println("The Roman Number is: "+romanNumber);
   System.out.println("Its Integer Value is: "+result);
 }

}

Output:

The Roman Number is: MCMXCIV
Its Integer Value is: 1994

The Roman Number is: DCCXCIX
Its Integer Value is: 799

5. Time Complexity

The time complexity of this code is O(n), where n is the length of Roman Number in String format as we are traversing String only once.

6. Conclusion

In this article, we implemented a simple java program to convert Roman numeral to Integer. Before the conversion, we have also implemented validation logic to make sure input string is a valid Roman numeral.

[social_share share_on="facebook,twitter,linkedin,whatsapp"][post_navigator in_same_term="true"]

Leave a Reply

Your email address will not be published. Required fields are marked *

Subscribe to our newletter

Get quality tutorials to your inbox. Subscribe now.