com.vladsch.flexmark.util.format.RomanNumeral Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of flexmark-util-format Show documentation
Show all versions of flexmark-util-format Show documentation
flexmark-java format utility classes
The newest version!
package com.vladsch.flexmark.util.format;
/*
taken from: http://math.hws.edu/eck/cs124/javanotes3/c9/ex-9-3-answer.html
An object of type RomanNumeral is an integer between 1 and 3999. It can
be constructed either from an integer or from a string that represents
a Roman numeral in this range. The function toString() will return a
standardized Roman numeral representation of the number. The function
toInt() will return the number as a value of type int.
*/
import java.util.regex.Pattern;
public class RomanNumeral {
private final int num; // The number represented by this Roman numeral.
/*
The following arrays are used by the toString() function to construct
the standard Roman numeral representation of the number. For each i,
the number numbers[i] is represented by the corresponding string, letters[i].
*/
private static final int[] numbers = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
private static final String[] letters = {
"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"
};
public static final Pattern ROMAN_NUMERAL =
Pattern.compile(
"M{0,3}(?:CM|DC{0,3}|CD|C{1,3})?(?:XC|LX{0,3}|XL|X{1,3})?(?:IX|VI{0,3}|IV|I{1,3})?");
public static final Pattern LOWERCASE_ROMAN_NUMERAL =
Pattern.compile(
"m{0,3}(?:cm|dc{0,3}|cd|c{1,3})?(?:xc|lx{0,3}|xl|x{1,3})?(?:ix|vi{0,3}|iv|i{1,3})?");
public static final Pattern LIMITED_ROMAN_NUMERAL =
Pattern.compile("(?:X{1,3})?(?:IX|VI{0,3}|IV|I{1,3})?");
public static final Pattern LIMITED_LOWERCASE_ROMAN_NUMERAL =
Pattern.compile("(?:x{1,3})?(?:ix|vi{0,3}|iv|i{1,3})?");
public RomanNumeral(int arabic) {
// Constructor. Creates the Roman number with the int value specified
// by the parameter. Throws a NumberFormatException if arabic is
// not in the range 1 to 3999 inclusive.
if (arabic < 1) {
throw new NumberFormatException("Value of RomanNumeral must be positive.");
}
if (arabic > 3999) {
throw new NumberFormatException("Value of RomanNumeral must be 3999 or less.");
}
num = arabic;
}
public RomanNumeral(String roman) {
// Constructor. Creates the Roman number with the given representation.
// For example, RomanNumeral("xvii") is 17. If the parameter is not a
// legal Roman numeral, a NumberFormatException is thrown. Both upper and
// lower case letters are allowed.
if (roman.length() == 0)
throw new NumberFormatException("An empty string does not define a Roman numeral.");
roman = roman.toUpperCase();
int i = 0; // A position in the string, roman;
int arabic =
0; // Arabic numeral equivalent of the part of the string that has been converted so far.
while (i < roman.length()) {
char letter = roman.charAt(i);
int number = letterToNumber(letter);
if (number < 0)
throw new NumberFormatException("Illegal character \"" + letter + "\" in roman numeral.");
i++;
if (i == roman.length()) {
// There is no letter in the string following the one we have just processed.
// So just add the number corresponding to the single letter to arabic.
arabic += number;
} else {
// Look at the next letter in the string. If it has a larger Roman numeral
// equivalent than number, then the two letters are counted together as
// a Roman numeral with value (nextNumber - number).
int nextNumber = letterToNumber(roman.charAt(i));
if (nextNumber > number) {
// Combine the two letters to get one value, and move on to next position in string.
arabic += (nextNumber - number);
i++;
} else {
// Don't combine the letters. Just add the value of the one letter onto the number.
arabic += number;
}
}
}
if (arabic > 3999)
throw new NumberFormatException("Roman numeral must have value 3999 or less.");
num = arabic;
}
private static int letterToNumber(char letter) {
// Find the integer value of letter considered as a Roman numeral. Return
// -1 if letter is not a legal Roman numeral. The letter must be upper case.
switch (letter) {
case 'I':
return 1;
case 'V':
return 5;
case 'X':
return 10;
case 'L':
return 50;
case 'C':
return 100;
case 'D':
return 500;
case 'M':
return 1000;
default:
return -1;
}
}
@Override
public String toString() {
// Return the standard representation of this Roman numeral.
StringBuilder roman = new StringBuilder();
int n = num;
for (int i = 0; i < numbers.length; i++) {
while (n >= numbers[i]) {
roman.append(letters[i]);
n -= numbers[i];
}
}
return roman.toString();
}
public int toInt() {
// Return the value of this Roman numeral as an int.
return num;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy