**1. Introduction**

The ancient Romans developed their own numeric system called Roman numerals. The system uses letters with different values to represent numbers. Roman numerals are still used today in some minor applications.

In this tutorial, we'll implement **simple converters that will transform numbers from one system to the other.**

**2. Roman Numerals**

In the Roman system, we have **7 symbols that represent numbers**:

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

Originally, people used to represent a 4 with IIII or 40 with XXXX. This can be quite uncomfortable to read. It's also easy to mistake four symbols next to each other for three symbols.

**Roman numerals use subtractive notation **to avoid such mistakes. Instead of saying *four times one* (IIII), one can say that it's *one less than five* (IV).

How's it important from our perspective? It's important because instead of simply adding numbers symbol by symbol, we might need to check the next symbol to determine if the number should be added or subtracted.

**3. Model**

Let's define an enum to represent the Roman Numerals:

```
enum RomanNumeral {
I(1), IV(4), V(5), IX(9), X(10),
XL(40), L(50), XC(90), C(100),
CD(400), D(500), CM(900), M(1000);
private int value;
RomanNumeral(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static List<RomanNumeral> getReverseSortedValues() {
return Arrays.stream(values())
.sorted(Comparator.comparing((RomanNumeral e) -> e.value).reversed())
.collect(Collectors.toList());
}
}
```

Notice that we've defined additional symbols to help out with subtractive notation. We have also defined an additional method named *getReverseSortedValues()*.

This method will allow us to explicitly retrieve the defined Roman numerals in descending value order.

**4. Roman to Arabic**

**Roman numerals can only represent integers between 1 to 4000**. We can use the following algorithm to convert a Roman numeral to an Arabic number (iterating through symbols in reverse order from *M* to *I*):

```
LET numeral be the input String representing an Roman Numeral
LET symbol be initialy set to RomanNumeral.values()[0]
WHILE numeral.length > 0:
IF numeral starts with symbol's name:
add symbol's value to the result
remove the symbol's name from the numeral's beginning
ELSE:
set symbol to the next symbol
```

**4.1. Implementation**

Next, we can implement the algorithm in Java:

```
public static int romanToArabic(String input) {
String romanNumeral = input.toUpperCase();
int result = 0;
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
int i = 0;
while ((romanNumeral.length() > 0) && (i < romanNumerals.size())) {
RomanNumeral symbol = romanNumerals.get(i);
if (romanNumeral.startsWith(symbol.name())) {
result += symbol.getValue();
romanNumeral = romanNumeral.substring(symbol.name().length());
} else {
i++;
}
}
if (romanNumeral.length() > 0) {
throw new IllegalArgumentException(input + " cannot be converted to a Roman Numeral");
}
return result;
}
```

**4.2. Test**

Finally, we can test the implementation:

```
@Test
void given2018Roman_WhenConvertingToArabic_ThenReturn2018() {
String roman2018 = "MMXVIII";
int result = RomanArabicConverter.romanToArabic(roman2018);
assertThat(result).isEqualTo(2018);
}
```

**5. Arabic to Roman**

We can use the following algorithm to convert from Arabic to Roman numerals (iterating through symbols in reverse order from *M* to *I*):

```
LET number be an integer between 1 and 4000
LET symbol be RomanNumeral.values()[0]
LET result be an empty String
WHILE number > 0:
IF symbol's value <= number:
append the result with the symbol's name
subtract symbol's value from number
ELSE:
pick the next symbol
```

**5.1. Implementation**

Next, we can now implement the algorithm:

```
public static String arabicToRoman(int number) {
if ((number <= 0) || (number > 4000)) {
throw new IllegalArgumentException(number + " is not in range (0,4000]");
}
List<RomanNumeral> romanNumerals = RomanNumeral.getReverseSortedValues();
int i = 0;
StringBuilder sb = new StringBuilder();
while ((number > 0) && (i < romanNumerals.size())) {
RomanNumeral currentSymbol = romanNumerals.get(i);
if (currentSymbol.getValue() <= number) {
sb.append(currentSymbol.name());
number -= currentSymbol.getValue();
} else {
i++;
}
}
return sb.toString();
}
```

**5.2. Test**

Finally, we can test the implementation:

```
@Test
void given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX() {
int arabic1999 = 1999;
String result = RomanArabicConverter.arabicToRoman(arabic1999);
assertThat(result).isEqualTo("MCMXCIX");
}
```

**6. Conclusion**

In this quick article, we've shown how to convert between Roman and Arabic numerals.

We have used an *enum *to represent the set of Roman numerals and we have created a utility class to perform the conversions.

The complete implementation and all tests can be found over on GitHub.

res – REST with Spring (eBook) (everywhere)