Javaでのローマ数字とアラビア数字の変換
1. 序章
古代ローマ人は、ローマ数字と呼ばれる独自の記数法を開発しました。 システムは、数値を表すために異なる値の文字を使用します。 ローマ数字は、今日でもいくつかのマイナーなアプリケーションで使用されています。
このチュートリアルでは、あるシステムから別のシステムに数値を変換する単純なコンバーターを実装します。
2. ローマ数字
ローマのシステムでは、数字を表す7つの記号があります。
- Iは1を表します
- Vは5を表します
- Xは10を表します
- Lは50を表します
- Cは100を表します
- Dは500を表します
- Mは1000を表します
もともと、人々はIIIIで4を、XXXXで40を表していました。 これは読むのが非常に不快な場合があります。 また、隣り合った4つのシンボルを3つのシンボルと間違えやすいです。
ローマ数字は、このような間違いを避けるために減算表記を使用します。 4回1(IIII)と言う代わりに、5未満(IV)と言うことができます。
私たちの観点からそれはどのように重要ですか? 重要なのは、単に記号ごとに数字を追加するのではなく、次の記号をチェックして、数字を加算または減算する必要があるかどうかを判断する必要がある場合があるためです。
3. モデル
ローマ数字を表す列挙型を定義しましょう。
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());
}
}
減算表記に役立つ追加の記号を定義していることに注意してください。 getReverseSortedValues()という名前の追加のメソッドも定義しました。
このメソッドを使用すると、定義されたローマ数字を値の降順で明示的に取得できます。
4. ローマ語からアラビア語
ローマ数字は1から4000までの整数のみを表すことができます。 次のアルゴリズムを使用して、ローマ数字をアラビア数字に変換できます(Mから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. 実装
次に、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
public void given2018Roman_WhenConvertingToArabic_ThenReturn2018() {
String roman2018 = "MMXVIII";
int result = RomanArabicConverter.romanToArabic(roman2018);
assertThat(result).isEqualTo(2018);
}
5. アラビア語からローマ語
次のアルゴリズムを使用して、アラビア数字からローマ数字に変換できます(Mから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. 実装
次に、アルゴリズムを実装できます。
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
public void given1999Arabic_WhenConvertingToRoman_ThenReturnMCMXCIX() {
int arabic1999 = 1999;
String result = RomanArabicConverter.arabicToRoman(arabic1999);
assertThat(result).isEqualTo("MCMXCIX");
}
6. 結論
この簡単な記事では、ローマ数字とアラビア数字を変換する方法を示しました。
列挙型を使用してローマ数字のセットを表し、変換を実行するためのユーティリティクラスを作成しました。
完全な実装とすべてのテストは、GitHubのにあります。